Responsive web design describes websites that respond to changes in screen / window size. It involves the use of flexible layouts, flexible images, and media queries. ### Key ideas - Flexible layouts: Use flexbox and grid layout to facilitate flexible layouts. - Flexible images: Use responsive image techniques (e.g. `background-size`, `srcset` + `sizes`, and `<picture>`) to adapt images to different screen sizes. - Media queries: Apply different styles based on device characteristics. ##### Target screen sizes - The smallest phones in common circulation rarely get smaller than 320px, so that should serve as a reliable lower end target. - The upper limit is harder to clarify. These days ultra-wide monitors aren't common; setting a max-width is best practice here. ##### Avoid fixed width and height *The number one enemy of flexibility is a fixed width (or height) element.* - An easy fix is replacing `width`/`height` with `max-width` or `min-height`. - In most cases, you should avoid setting height. Instead, prefer using margin and padding to increase space around your content. ##### The viewport meta tag Originally, websites were not optimized for small mobile phones and displayed a zoomed-out version of the page. To set the initial width of the webpage to the device’s width, use the viewport meta tag in the `<head>`: ```html <meta name="viewport" content="width=device-width, initial-scale=1"> ``` # Responsive Images The most basic problem faced when working with responsive images is the aspect ratio. If an image is given a flexible width, and the height is set to `auto`, it should retain its aspect ration. Responsive images: - Optimize bandwidth usage and page load times - Enhance user experience - Maintain image quality on high-resolution displays If the image is part of the content, use HTML. If the image is part of the background, use CSS. ## Responsive content images with HTML If your only goal is increased performance: use `srcset` + `sizes`. If you also need design control: use `<picture>`. #### srcset and sizes We can use `srcset` and `sizes` to provide additional source images. - `srcset` provides multiple image sources based on pixel ratio or viewport width. - `sizes` helps the browser determine which image to load before CSS loads. ```html <img src="clouds-800w.jpg" srcset="clouds-small.jpg 300w, clouds-medium.jpg 600w clouds-large.jpg 1200w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px 800px" /> ``` `srcset` specifies multiple images and what size each image is: 1. An image filename (`clouds-small.jpg`) 2. The image's intrinsic width in pixels (`300w`) `sizes` defines a set of media conditions (e.g. screen widths) and indicates what image size to choose at certain conditions: 1. A media condition: `(max-width:480px)`. "When the viewport is 480 px or less" 2. The width of the slot the image will fill when the media conditions is true (`800px`) #### \<picture> element The `<picture>` element offers more flexibility, specifying which image is loaded based on different conditions. You specify multiple `<source>` elements with different media queries and image formats, falling back to a default `<img>` element. ```html <picture> <source media="(max-width: 799px)" srcset="portrait-480w.jpg" /> <source media="(min-width: 800px)" srcset="portrait-800w.jpg" /> <img src="portrait-800w.jpg" /> </picture> ``` `<picture>`: a wrapper element containing several `<source>`s, followed by an `<img>`. `<source>`: defines the media conditions and the associated image source. `<img>`: acts as a fallback if none of the `<source>` conditions are met. #### object-fit `object-fit` CSS property controls how an `<img>` is resized to fit its container. - Values: `fill` (default), `contain`, `cover`, `scale-down`, `none`. ## Responsive background images with CSS `background-position` positions the background within its container, relative to the edges or center of the element. - Values: `top`, `right`, `bottom`, `left`, `center`, `<percentage>`, `<pixels>` `background-size` determines how a background image should be resized to fit its container. - Values: `contain`, `cover`, `auto`, `<length>`, `<percentage>` ```css .hero { background-image: url('small.jpg'); background-size: cover; background-position: center; } @media (min-width: 768px) { .hero { background-image('medium.jpg'); } } ``` # Media Queries Introduced in CSS3, media queries enable responsive designs, adapting to media type (e.g. print vs screen) or other characteristics like screen size, orientation, reduced motion, etc. The basic syntax of a media query is as follows: ```css /* media-type: the type of media. e.g. screen, print, speech, all condition: e.g. min-width, resolution, orientation, etc. */ @media [media-type] and (condition) { /* CSS rules */ } ``` - Media types: `all` (default), `print` (printer), `screen`. - Media features are the conditions you can test for. - `width`, `min-width`, `orientation`, `resolution`, `hover`, etc. - Logical operators: `not`, `and`, `only`, `or`. It's best practice to have a mobile-first approach, defining the base styles for mobile. #### Breakpoints Breakpoints are the viewport widths at which your layout adapts to different screen sizes. Common breakpoints include: - Mobile: up to 767px - Tablet: 768px to 1023px - Desktop: 1024px and above Limit breakpoints (typically 3-5) don't create one for every device. #### Concise CSS example ```css /* Base styles (mobile-first) */ body { font-family: Arial, sans-serif; } .container { display: flex; flex-direction: column; } header, nav, main, aside { padding: 10px; } /* Tablet styles */ @media screen and (min-width: 768px) { .container { flex-direction: row; flex-wrap: wrap; } nav { width: 30%; } main { width: 70%; } aside { width: 100%; } } /* Desktop styles */ @media screen and (min-width: 1024px) { nav { width: 20%; } main { width: 60%; } aside { width: 20%; order: 2; } main { order: 3; } } /* Print styles */ @media print { nav, aside { display: none; } main { width: 100%; } } /* Dark mode */ @media (prefers-color-scheme: dark) { body { background-color: #333; color: #fff; } } ```