Responsive CSS

Responsive CSS

References

  • https://www.youtube.com/watch?v=vQDgoQKfdzM
  • https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries

Notes

  • By default, Bootstrap automatically includes the viewport meta tag. This tag is crucial for responsive design on mobile devices, ensuring proper rendering and zooming. It essentially tells the browser how to scale the page to fit the device's screen. But, it is always a good mesure to double check this. Otherwse, you will get a lot of headaches.
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
  • Always start write media query from small screen to big screen.

Switch media query based on screen size

  • Note: you can replace all these media queries for font-size with clamp() function.
h1 {
    font-size: 2rem;
    
    @media(with >= 40em) {
        // 640px
        font-size: 3rem;
    }
    
    @media(with >= 60em) {
        // 960px
        font-size: 4rem;
    }
}

Image

Basic must have properties for image

img {
    max-width: 100%; /* Prevent image being larger that its container. */
    height: auto;    /* Scale height automatically to preserve the aspect ratio */
}

Display different image for different device

<picture>
    <!-- Use this pic if width is 40em(640px) -->
    <source media="(min-width: 40em)" srcset="cat-1920.jpg">

    <img src="crop.jpg" /><!-- Fallback image and also happens to be cropped image which give a zoom in effect. -->
</picture>

Layout: Grid or Flexbox

  • With grid layout, you will have more control than flexbox.

Grid

.cards {
    display: grid,
    grid-template-columns: repeat(4, 1fr); /* 4 cols */
    gap: 12px
    grid-auto-rows: 1fr;
}

.card { ... }

Mobile grid

.cards {
    display: grid,
    grid-template-columns: 1fr; /* 1 cols */
    gap: 14px
    grid-auto-rows: 1fr;
    
    @meda (width >=40em) {
        grid-template-columns: repeat(2, 1fr); /* 2 cols */
    }

    @meda (width >=60em) {
        grid-template-columns: repeat(4, 1fr); /* 2 cols */
    }
}
  • Drawback, uneven numbers of items: e.g. first row has 3 item whereas 2nd row has 1. It is prefer to have 2 items on the first and 2nd row.
/*Or, without media queries. 
Let browser decide how many columns do you want at any given viewport
*/
.cards {
    display: grid,
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); /* 15rem=240px */
    gap: 14px
    grid-auto-rows: 1fr;
    
}

Mobile flex

  • By default, flex will fit all items in one single row(item with diff width).
  • Set flex: 1 on the items to make all items to have the same width.
  • Can't force children items to have the same height.
.cards {
    display: flex,
    flex-wrap: wrap; /*Last item on last row will take full width.*/
}

.card {
    flex: 1; /* flex: 0 0 240px -> min width is 240px */
}

Flex with media queries

.cards {
    display: flex,
    flex-wrap: wrap; /*Last item on last row will take full width.*/
    gap: 14px;
}

.card {
    flex: 100%; /* 1 column only */
    
    @meda (width >=40em) {
        /* 2 coluns. Logically it should be 50% but we need to factor in
            the 14 px gap(14/2)=7
        */
        flex: calc(50% - 7px); 
    }

    @meda (width >=60em) {
        flex: 23%; /* calc(25% - ?px); */
    }
    
}

Resize image

object-fit has effect only if you let the browser the width and height of the image. In my case, I used max-width and height.

.imgItself {
    max-width: 100%; /* Prevent image being larger that its container. */
    height: auto;    /* Scale height automatically to preserve the aspect ratio */
        
    object-fit: contain;
}