![Pete LePage](https://web.dev/images/authors/petelepage.jpg) Pete LePage [X](https://twitter.com/petele) [GitHub](https://github.com/petele) [Mastodon](https://techhub.social/@petele) [Homepage](https://petelepage.com/) ![Rachel Andrew](https://web.dev/images/authors/rachelandrew.jpg) Rachel Andrew Technical Writer [GitHub](https://github.com/rachelandrew) [LinkedIn](https://www.linkedin.com/in/rachelandrew) [Mastodon](https://front-end.social/@rachelandrew) [Bluesky](https://bsky.app/profile/rachelandrew.bsky.social) [Homepage](https://rachelandrew.co.uk)

<br />

> [!NOTE]
> **Note:** For a deeper dive into responsive web design, see our [Learn Design](https://web.dev/learn/design) course.

As the number of mobile phone users on the internet increases, it has become
more and more important for web designers to lay out content in ways that work
well for a variety of screen sizes. Responsive web design, originally defined by
Ethan Marcotte in [A List Apart](http://alistapart.com/article/responsive-web-design/),
is a design strategy that responds to users' needs and their devices'
capabilities by changing a site's layout to suit the device being used. For
example, a responsive site might show content in a single-column view on a phone,
two columns on a tablet, and three or four columns on a desktop computer.
As the screen gets wider, the widget changes shape in response.

Because internet-capable devices have so many possible screen sizes, it's
important for your site to adapt to any existing or future screen size. Modern
responsive design also accounts for modes of interaction such as touch screens.
The goal is to optimize the experience for everyone.

## Set the viewport

Pages optimized for a variety of devices must include a meta viewport tag in the
head of the document. This tag tells the browser how to control the page's
dimensions and scaling.

To try to provide the best experience, mobile browsers render the page at a
desktop screen width (usually about `980px`, though this varies across devices),
and then try to make the content look better by increasing font sizes and
scaling the content to fit the screen. This can make fonts look inconsistent and
require users to zoom in to see and interact with the content.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        ...
        <meta name="viewport" content="width=device-width, initial-scale=1">
        ...
      </head>
      ...

Using the meta viewport value `width=device-width` tells the page to match the
screen's width in device-independent pixels (DIP), a standard visual pixel unit
(which can be made up of many physical pixels on a high-density screen). This
lets the page reflow content to match different screen sizes.
![A
page with the text hard to read because it's very zoomed out.](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-page-the-t-faa09126e69d.png) A page without the viewport meta tag loads very zoomed out, making the text hard to read. ![The same page with the text at a size that can be read.](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-the-same-page-9ac43367e5e0c.png) With the viewport meta tag set, you can read the page without zooming in.

[Some browsers](https://css-tricks.com/probably-use-initial-scale1/) keep the
page's width constant when rotating to landscape mode, and zoom to fill the
screen instead of reflowing. Adding the value `initial-scale=1` tells browsers
to set a 1:1 relationship between CSS pixels and device-independent pixels
regardless of device orientation, letting the page take advantage of the full
landscape width.

> [!CAUTION]
> **Caution:** To ensure that older browsers can properly parse the attributes, use a comma to separate attributes.

The [Does not have a `<meta name="viewport">` tag with `width` or `initial-scale`](https://developer.chrome.com/docs/lighthouse/pwa/viewport)
Lighthouse audit can help you automate the process of making sure your HTML
documents use the viewport meta tag correctly.

> [!CAUTION]
> **Caution:** In addition to `initial-scale`, the `minimum-scale`, `maximum-scale`, and `user-scalable` attributes are also available. We don't recommend using these attributes because they can prevent the user from zooming the viewport, potentially causing accessibility issues.

## Size content to the viewport

On both desktop and mobile devices, users are used to scrolling websites
vertically but not horizontally. Forcing the user to scroll horizontally or to
zoom out to see the whole page causes a poor user experience.

When developing a mobile site with a meta viewport tag, it's common to
accidentally create page content that doesn't quite fit within the specified
viewport. For example, an image displayed wider than the viewport can cause
horizontal scrolling. To prevent this, adjust your content to fit inside the
viewport.

The [Content is not sized correctly for the viewport](https://developer.chrome.com/docs/lighthouse/pwa/content-width)
Lighthouse audit can help you automate the process of detecting overflowing
content.

### Images

An image with fixed dimensions causes the page to scroll if it's larger than the
viewport. We recommend giving all images a `max-width` of `100%`, which shrinks
images to fit the available space while preventing them from stretching beyond
their initial size.

In most cases, you can do this by adding the following to your style sheet:

    img {
      max-width: 100%;
      display: block;
    }

#### Add the dimensions of the image to the img element

Even when you set `max-width: 100%`, we still recommend adding `width` and
`height` attributes to your `<img>` tags so the browser can reserve space for
images before they load. This helps prevent [layout shifts](https://web.dev/articles/optimize-cls).

### Layout

Because screen dimensions and width in CSS pixels vary widely between devices
(for example, between phones and tablets, and even between different phones),
content shouldn't rely on a particular viewport width to render well.

In the past, this required setting layout elements in percentages. Using pixel
measurements requires the user to scroll horizontally on small screens:
![A two-column layout with most of the second column outside the viewport](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-column-lay-cb8a5725d0a67.jpg) A floated layout using pixels. [See this example on CodePen](https://codepen.io/web-dot-dev/pen/vEOwwJQ).

Using percentages instead makes the columns narrower on smaller screens, because
each column always takes up the same percentage of the screen width:
<iframe height="406" style="width: 100%;" scrolling="no" title="Responsive basics: floats percent" src="https://codepen.io/web-dot-dev/embed/bNdyyYG?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/bNdyyYG"&amp;amp;gt; Responsive basics: floats percent&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

Modern CSS layout techniques such as flexbox, grid layout, and multicol make
creating these flexible grids much easier.

#### Flexbox

Use Flexbox when you have a set of items of different sizes and you want them to
fit comfortably in a row or multiple rows, with smaller items taking up less
space and larger ones taking more space.

    .items {
      display: flex;
      justify-content: space-between;
    }

You can use Flexbox to display items as a single row, or wrapped onto multiple
rows as the available space decreases.
<iframe height="300" style="width: 100%;" scrolling="no" title="Responsive basics: flex example" src="https://codepen.io/web-dot-dev/embed/PwqvvOv?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/PwqvvOv"&amp;amp;gt; Responsive basics: flex example&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

[Read more about Flexbox](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Flexbox).

#### CSS grid layout

CSS Grid Layout creates flexible grids. You can improve the earlier floated
example using use grid layout and the `fr` unit, which represents a portion of
the available space in the container.

    .container {
      display: grid;
      grid-template-columns: 1fr 3fr;
    }

<iframe height="401" style="width: 100%;" scrolling="no" title="Responsive Basics: two column grid" src="https://codepen.io/web-dot-dev/embed/dPoEEJq?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/dPoEEJq"&amp;amp;gt; Responsive Basics: two column grid&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

You can also use grid to create regular grid layouts with as many items
as can fit. The number of available tracks is reduced as the screen size
decreases. The following demo shows a grid containing as many cards as fit on
each row, with a minimum size of `200px`.
<iframe height="300" style="width: 100%;" scrolling="no" title="Responsive Basics: Grid as many as fit" src="https://codepen.io/web-dot-dev/embed/emNaaVW?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/emNaaVW"&amp;amp;gt; Responsive Basics: Grid as many as fit&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

[Read more about CSS Grid Layout](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Grids)

#### Multiple-column layout

For some types of layout, you can use Multiple-column Layout (Multicol),
which creates responsive numbers of columns with the `column-width` property.
In the following demo, the page adds columns when there's
room for another `200px` column.
<iframe height="370" style="width: 100%;" scrolling="no" title="Responsive Basics: Multicol" src="https://codepen.io/web-dot-dev/embed/wBabbmv?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/wBabbmv"&amp;amp;gt; Responsive Basics: Multicol&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

[Read more about Multicol](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Multiple-column_Layout)

## Use CSS media queries for responsiveness

Sometimes you might need to make more extensive changes to your layout to
support certain screen sizes than the techniques described previously allow.
This is where media queries become useful.

Media queries are simple filters that you can apply to CSS styles, to change
those styles based on the types of device rendering the content. They can also
change styling based on device features including width, height, orientation,
and whether the device is being used as a touchscreen.

To provide different styles for printing, you can target an output type and
include a style sheet for print styles:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        ...
        <link rel="stylesheet" href="print.css" media="print">
        ...
      </head>
      ...

You can also use a media query to include print styles in your main style sheet:

    @media print {
      /* print styles go here */
    }

> [!NOTE]
> **Note:** You can also include separate stylesheets in your main CSS file using the `@import` syntax, `@import url(print.css) print;`. However, we don't recommend this for performance reasons. See [Avoid CSS imports](https://web.dev/articles/critical-rendering-path/page-speed-rules-and-recommendations#avoid_css_imports) for more details.

For responsive web design, the most common queries are for device features, so
you can customize your layout for touchscreens or smaller screens.

### Media queries based on viewport size

Media queries let you create a responsive experience that applies specific
styles to specific screen size. Queries for screen size can test for the
following things:

- `width` (`min-width`, `max-width`)
- `height` (`min-height`, `max-height`)
- `orientation`
- `aspect-ratio`

<iframe height="300" style="width: 100%;" scrolling="no" title="Responsive Basics: Size media queries" src="https://codepen.io/web-dot-dev/embed/LEVoomB?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/LEVoomB"&amp;amp;gt; Responsive Basics: Size media queries&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

### Media queries based on device capability

Given the range of devices available, developers can't assume
that every large device is a regular desktop or laptop computer, or that every
small device uses a touchscreen. Some newer additions to the media queries
specification let you test for features such as the type of pointer used to
interact with the device and whether the user can hold a pointer over
elements.

- `hover`
- `pointer`
- `any-hover`
- `any-pointer`

Try viewing this demo on different devices,
such as a regular desktop computer and a phone or tablet.
<iframe height="300" style="width: 100%;" scrolling="no" title="Responsive Basics: Pointer and hover" src="https://codepen.io/web-dot-dev/embed/KwpLLeg?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/KwpLLeg"&amp;amp;gt; Responsive Basics: Pointer and hover&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

These newer features have good support in all modern browsers. Find out more on
the MDN pages for [hover](https://developer.mozilla.org/docs/Web/CSS/@media/hover),
[any-hover](https://developer.mozilla.org/docs/Web/CSS/@media/any-hover),
[pointer](https://developer.mozilla.org/docs/Web/CSS/@media/pointer), and
[any-pointer](https://developer.mozilla.org/docs/Web/CSS/@media/any-pointer).

#### Use `any-hover` and `any-pointer`

The features `any-hover` and `any-pointer` test if the user can hold a pointer
over elements (often called *hovering* ), or use a pointer at all, even if it's
not the primary way they interact with their device. Be very careful when using
these, for example to avoid forcing a touchscreen user to switch to a mouse.
However, `any-hover` and `any-pointer` can be useful if it's important to
determine what kind of device a user has. For example, a laptop with a
touchscreen and trackpad should match coarse and fine pointers, in addition to
the ability to hover.

## How to choose breakpoints

Don't define breakpoints based on device classes, or any product, brand name, or
operating system. This makes your code difficult to maintain. Instead, let
the content determine how its layout changes to fit the container.

### Pick major breakpoints by starting small, then working up

Design the content to fit on a small screen size first, then expand the screen
until a breakpoint becomes necessary. This lets you minimize the number of
breakpoints on your page and optimize them based on content.

The following example walks through the weather forecast widget example at the
beginning of this page. The first step is to make the forecast look good on a
small screen:
![A weather app at a mobile width](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-weather-app-8807746eddfbe.png) The app at a narrow width.

Next, resize the browser until there's too much whitespace between the elements
to make the widget look good. The decision is subjective, but more than `600px`
is certainly too wide.
![A weather app with wide gaps between items](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-weather-app-236b1e89bc871.png) At this size, the app's layout should probably change.

To insert a breakpoint at `600px`, create two media queries at the end of your
CSS for the component: one to use when the browser is `600px` or narrower, and
one for when it's wider than `600px`.

    @media (max-width: 600px) {

    }

    @media (min-width: 601px) {

    }

Finally, refactor the CSS. Inside the media query for a `max-width` of `600px`,
add the CSS which is only for small screens. Inside the media query for a
`min-width` of `601px` add CSS for larger screens.

#### Pick minor breakpoints when necessary

In addition to choosing major breakpoints when layout changes significantly,
it's also helpful to adjust for minor changes. For example, between major
breakpoints it can be helpful to adjust the margins or padding on an element,
or increase the font size to make it feel more natural in the layout.

This example follows the same pattern as the previous one, starting with
optimizing smaller screen layouts. First, boost the font when the viewport
width is greater than `360px`. After that, when there's enough space, you can
separate the high and low temperatures so they're on the same line, and make the
weather icons larger.

    @media (min-width: 360px) {
      body {
        font-size: 1.0em;
      }
    }

    @media (min-width: 500px) {
      .seven-day-fc .temp-low,
      .seven-day-fc .temp-high {
        display: inline-block;
        width: 45%;
      }

      .seven-day-fc .seven-day-temp {
        margin-left: 5%;
      }

      .seven-day-fc .icon {
        width: 64px;
        height: 64px;
      }
    }

For large screens, we recommend limiting the maximum width of the forecast panel
so it doesn't use the whole screen width.

    @media (min-width: 700px) {
      .weather-forecast {
        width: 700px;
      }
    }

<iframe height="462" style="width: 100%;" scrolling="no" title="ResponsiveBasics weather forecast demo" src="https://codepen.io/web-dot-dev/embed/Pwqvvpg?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen &amp;amp;lt;a href="https://codepen.io/web-dot-dev/pen/Pwqvvpg"&amp;amp;gt; Responsive Basics weather forecast demo&amp;amp;lt;/a&amp;amp;gt; by web.dev (&amp;amp;lt;a href="https://codepen.io/web-dot-dev"&amp;amp;gt;@web-dot-dev&amp;amp;lt;/a&amp;amp;gt;) on &amp;amp;lt;a href="https://codepen.io"&amp;amp;gt;CodePen&amp;amp;lt;/a&amp;amp;gt;. </iframe>

### Optimize text for reading

Classic readability theory suggests that an ideal column should contain 70 to 80
characters per line (about 8 to 10 words in English). Consider adding a
breakpoint every time the width of a text block grows past about 10 words.
![A page of text on a mobile device](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-page-text-e1d8d10e2e41f.jpg) Text on a mobile device. ![A page of text on a desktop browser](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-a-page-text-6d4928468315d.jpg) The same text in a desktop browser with a breakpoint added to constrain the line length.

In this example, the Roboto font at `1em` produces 10 words per line on the
smaller screen, but larger screens need a breakpoint. In this case, if the
browser width is greater than `575px`, the ideal content width is `550px`.

    @media (min-width: 575px) {
      article {
        width: 550px;
        margin-left: auto;
        margin-right: auto;
      }
    }

### Avoid hiding content (:#avoid-hiding-content)

Be careful when choosing what content to hide or show depending on screen size.
Don't hide content just because you can't fit it on the screen. Screen size
doesn't predict what a user might want to see. For example, removing the pollen
count from the weather forecast could be a serious issue for springtime allergy
sufferers who need that information to decide whether they can go outside.

## View media query breakpoints in Chrome DevTools

After you set up your media query breakpoints, check how they affect your site's
appearance. You could resize your browser window to trigger the breakpoints,
but Chrome DevTools has a built-in feature that shows how a page looks under
different breakpoints.
![DevTools with our weather app open and a width of 822 pixels selected.](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-devtools-our-1a065c0eb725a.png) DevTools showing the weather app at a wider viewport size. ![DevTools with our weather app open and a width of 436 pixels selected.](https://web.dev/static/articles/responsive-web-design-basics/image/screenshot-devtools-our-d104f520772db.png) DevTools showing the weather app at a narrower viewport size.

To view your page under different breakpoints:

1. [Open DevTools](https://developer.chrome.com/docs/devtools/open).
2. Turn on [Device Mode](https://developer.chrome.com/docs/devtools/device-mode/#toggle). This opens in [responsive mode](https://developer.chrome.com/docs/devtools/device-mode/#responsive) by default.
3. To see your media queries, open the Device Mode menu and select [Show media queries](https://developer.chrome.com/docs/devtools/device-mode/#queries). This shows your breakpoints as colored bars above your page.
4. Click one of the bars to view your page while that media query is active. Right-click a bar to jump to that media query's definition.