Positioning - Learn web development

Positioning
===========

* Previous
* Overview: CSS layout
* Next

Positioning allows you to take elements out of normal document flow and make them behave differently, for example, by sitting on top of one another or by always remaining in the same place inside the browser viewport. This article explains the different `position` values and how to use them.

|  |  |
| --- | --- |
| Prerequisites: |
 HTML basics (study
 Introduction to HTML), and an idea of How CSS works (study
 Introduction to CSS.)
  |
| Objective: | To learn how CSS positioning works. |

We'd like you to do the following exercises on your local computer. If possible, grab a copy of `0_basic-flow.html` from our GitHub repo (source code here) and use that as a starting point.

Introducing positioning
-----------------------

Positioning allows us to produce interesting results by overriding normal document flow. What if you want to slightly alter the position of some boxes from their default flow position to give a slightly quirky, distressed feel? Positioning is your tool. Or what if you want to create a UI element that floats over the top of other parts of the page and/or always sits in the same place inside the browser window no matter how much the page is scrolled? Positioning makes such layout work possible.

There are a number of different types of positioning that you can put into effect on HTML elements. To make a specific type of positioning active on an element, we use the `position` property.

Static positioning
------------------

Static positioning is the default that every element gets. It just means "put the element into its normal position in the document flow — nothing special to see here."

To see this (and get your example set up for future sections) first add a `class` of `positioned` to the second `<p>` in the HTML:

```html
<p class="positioned">…</p>
```

Now add the following rule to the bottom of your CSS:

```css
.positioned {
  position: static;
  background: yellow;
}
```

If you save and refresh, you'll see no difference at all, except for the updated background color of the 2nd paragraph. This is fine — as we said before, static positioning is the default behavior!

**Note:** You can see the example at this point live at `1_static-positioning.html` (see source code).

Relative positioning
--------------------

Relative positioning is the first position type we'll take a look at. This is very similar to static positioning, except that once the positioned element has taken its place in the normal flow, you can then modify its final position, including making it overlap other elements on the page. Go ahead and update the `position` declaration in your code:

```css
position: relative;
```

If you save and refresh at this stage, you won't see a change in the result at all. So how do you modify the element's position? You need to use the `top`, `bottom`, `left`, and `right` properties, which we'll explain in the next section.

### Introducing top, bottom, left, and right

`top`, `bottom`, `left`, and `right` are used alongside `position` to specify exactly where to move the positioned element to. To try this out, add the following declarations to the `.positioned` rule in your CSS:

```css
top: 30px;
left: 30px;
```

**Note:** The values of these properties can take any units you'd reasonably expect: pixels, mm, rems, %, etc.

If you now save and refresh, you'll get a result something like this:
```

<h1>Relative positioning</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">
  By default we span 100% of the width of our parent element, and we are as tall
  as our child content. Our total width and height is our content + padding +
  border width/height.
</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  Inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```

```
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

.positioned {
  position: relative;
  background: yellow;
  top: 30px;
  left: 30px;
}
```

Cool, huh? Ok, so this probably wasn't what you were expecting. Why has it moved to the bottom and to the right if we specified *top* and *left*? This may seem counterintuitive. You need to think of it as if there's an invisible force that pushes the specified side of the positioned box, moving it in the opposite direction. So, for example, if you specify `top: 30px;`, it's as if a force will push the top of the box, causing it to move downwards by 30px.

**Note:** You can see the example at this point live at `2_relative-positioning.html` (see source code).

Absolute positioning
--------------------

Absolute positioning brings very different results.

### Setting position: absolute

Let's try changing the position declaration in your code as follows:

```css
position: absolute;
```

If you now save and refresh, you should see something like so:
```

<h1>Absolute positioning</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">
  By default we span 100% of the width of our parent element, and we are as tall
  as our child content. Our total width and height is our content + padding +
  border width/height.
</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```

```
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

.positioned {
  position: absolute;
  background: yellow;
  top: 30px;
  left: 30px;
}
```

First of all, note that the gap where the positioned element should be in the document flow is no longer there — the first and third elements have closed together like it no longer exists! Well, in a way, this is true. An absolutely positioned element no longer exists in the normal document flow. Instead, it sits on its own layer separate from everything else. This is very useful: it means that we can create isolated UI features that don't interfere with the layout of other elements on the page. For example, popup information boxes, control menus, rollover panels, UI features that can be dragged and dropped anywhere on the page, and so on.

Second, notice that the position of the element has changed. This is because `top`, `bottom`, `left`, and `right` behave in a different way with absolute positioning. Rather than positioning the element based on its relative position within the normal document flow, they specify the distance the element should be from each of the containing element's sides. So in this case, we are saying that the absolutely positioned element should sit 30px from the top of the "containing element" and 30px from the left. (In this case, the "containing element" is the **initial containing block**. See the section below for more information)

**Note:** You can use `top`, `bottom`, `left`, and `right` to resize elements if you need to. Try setting `top: 0; bottom: 0; left: 0; right: 0;` and `margin: 0;` on your positioned elements and see what happens! Put it back again afterwards…

**Note:** Yes, margins still affect positioned elements. Margin collapsing doesn't, however.

**Note:** You can see the example at this point live at `3_absolute-positioning.html` (see source code).

### Positioning contexts

Which element is the "containing element" of an absolutely positioned element? This is very much dependent on the position property of the ancestors of the positioned element (See Identifying the containing block).

If no ancestor elements have their position property explicitly defined, then by default all ancestor elements will have a static position. The result of this is the absolutely positioned element will be contained in the **initial containing block**. The initial containing block has the dimensions of the viewport and is also the block that contains the `<html>` element. In other words, the absolutely positioned element will be displayed outside of the `<html>` element and be positioned relative to the initial viewport.

The positioned element is nested inside the `<body>` in the HTML source, but in the final layout it's 30px away from the top and the left edges of the page. We can change the **positioning context**, that is, which element the absolutely positioned element is positioned relative to. This is done by setting positioning on one of the element's ancestors: to one of the elements it's nested inside of (you can't position it relative to an element it's not nested inside of). To see this, add the following declaration to your `body` rule:

```css
position: relative;
```

This should give the following result:
```

<h1>Positioning context</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">
  Now I'm absolutely positioned relative to the
  <code><body></code> element, not the <code><html></code> element!
</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```

```
body {
  width: 500px;
  margin: 0 auto;
  position: relative;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

.positioned {
  position: absolute;
  background: yellow;
  top: 30px;
  left: 30px;
}
```

The positioned element now sits relative to the `<body>` element.

**Note:** You can see the example at this point live at `4_positioning-context.html` (see source code).

### Introducing z-index

All this absolute positioning is good fun, but there's another feature we haven't considered yet. When elements start to overlap, what determines which elements appear over others and which elements appear under others? In the example we've seen so far, we only have one positioned element in the positioning context, and it appears on the top since positioned elements win over non-positioned elements. What about when we have more than one?

Try adding the following to your CSS to make the first paragraph absolutely positioned too:

```css
p:nth-of-type(1) {
  position: absolute;
  background: lime;
  top: 10px;
  right: 30px;
}
```

At this point you'll see the first paragraph colored lime, moved out of the document flow, and positioned a bit above from where it originally was. It's also stacked below the original `.positioned` paragraph where the two overlap. This is because the `.positioned` paragraph is the second paragraph in the source order, and positioned elements later in the source order win over positioned elements earlier in the source order.

Can you change the stacking order? Yes, you can, by using the `z-index` property. "z-index" is a reference to the z-axis. You may recall from previous points in the course where we discussed web pages using horizontal (x-axis) and vertical (y-axis) coordinates to work out positioning for things like background images and drop shadow offsets. For languages that run left to right, (0,0) is at the top left of the page (or element), and the x- and y-axes run across to the right and down the page.

Web pages also have a z-axis: an imaginary line that runs from the surface of your screen towards your face (or whatever else you like to have in front of the screen). `z-index` values affect where positioned elements sit on that axis; positive values move them higher up the stack, negative values move them lower down the stack. By default, positioned elements all have a `z-index` of `auto`, which is effectively 0.

To change the stacking order, try adding the following declaration to your `p:nth-of-type(1)` rule:

```css
z-index: 1;
```

You should now see the lime paragraph on top:
```

<h1>z-index</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">
  Now I'm absolutely positioned relative to the
  <code><body></code> element, not the <code><html></code> element!
</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```

```
body {
  width: 500px;
  margin: 0 auto;
  position: relative;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

.positioned {
  position: absolute;
  background: yellow;
  top: 30px;
  left: 30px;
}

p:nth-of-type(1) {
  position: absolute;
  background: lime;
  top: 10px;
  right: 30px;
  z-index: 1;
}
```

Note that `z-index` only accepts unitless index values; you can't specify that you want one element to be 23 pixels up the Z-axis — it doesn't work like that. Higher values will go above lower values and it's up to you what values you use. Using values of 2 or 3 would give the same effect as values of 300 or 40000.

**Note:** You can see an example for this live at `5_z-index.html` (see source code).

Fixed positioning
-----------------

Let's now look at fixed positioning. This works in exactly the same way as absolute positioning, with one key difference: whereas absolute positioning fixes an element in place relative to its nearest positioned ancestor (the initial containing block if there isn't one), **fixed positioning** *usually* fixes an element in place relative to the visible portion of the viewport. (An exception to this occurs if one of the element's ancestors is a fixed containing block because its transform property has a value other than *none*.) This means that you can create useful UI items that are fixed in place, like persistent navigation menus that are always visible no matter how much the page scrolls.

Let's put together a simple example to show what we mean. First of all, delete the existing `p:nth-of-type(1)` and `.positioned` rules from your CSS.

Now update the `body` rule to remove the `position: relative;` declaration and add a fixed height, like so:

```css
body {
  width: 500px;
  height: 1400px;
  margin: 0 auto;
}
```

Now we're going to give the h1 element `position: fixed;` and have it sit at the top of the viewport. Add the following rule to your CSS:

```css
h1 {
  position: fixed;
  top: 0;
  width: 500px;
  margin-top: 0;
  background: white;
  padding: 10px;
}
```

The `top: 0;` is required to make it stick to the top of the screen. We give the heading the same width as the content column and then a white background and some padding and margin so the content won't be visible underneath it.

If you save and refresh, you'll see a fun little effect of the heading staying fixed — the content appears to scroll up and disappear underneath it. But notice how some of the content is initially clipped under the heading. This is because the positioned heading no longer appears in the document flow, so the rest of the content moves up to the top. We could improve this by moving the paragraphs all down a bit. We can do this by setting some top margin on the first paragraph. Add this now:

```css
p:nth-of-type(1) {
  margin-top: 60px;
}
```

You should now see the finished example:
```

<h1>Fixed positioning</h1>

<p>
  I am a basic block level element. My adjacent block level elements sit on new
  lines below me.
</p>

<p class="positioned">I'm not positioned any more.</p>

<p>
  We are separated by our margins. Because of margin collapsing, we are
  separated by the width of one of our margins, not both.
</p>

<p>
  Inline elements <span>like this one</span> and <span>this one</span> sit on
  the same line as one another, and adjacent text nodes, if there is space on
  the same line. Overflowing inline elements
  <span>wrap onto a new line if possible — like this one containing text</span>,
  or just go on to a new line if not, much like this image will do:
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```

```
body {
  width: 500px;
  height: 1400px;
  margin: 0 auto;
}

p {
  background: aqua;
  border: 3px solid blue;
  padding: 10px;
  margin: 10px;
}

span {
  background: red;
  border: 1px solid black;
}

h1 {
  position: fixed;
  top: 0px;
  width: 500px;
  background: white;
  padding: 10px;
}

p:nth-of-type(1) {
  margin-top: 60px;
}
```

**Note:** You can see an example for this live at `6_fixed-positioning.html` (see source code).

Sticky positioning
------------------

There is another position value available called `position: sticky`, which is somewhat newer than the others. This is basically a hybrid between relative and fixed position. It allows a positioned element to act like it's relatively positioned until it's scrolled to a certain threshold (e.g., 10px from the top of the viewport), after which it becomes fixed.

### Basic example

Sticky positioning can be used, for example, to cause a navigation bar to scroll with the page until a certain point and then stick to the top of the page.
```

<h1>Sticky positioning</h1>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
  laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
  tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
  neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
  volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
  pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
  lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>

<div class="positioned">Sticky</div>

<p>
  Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
  ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
  est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
  tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus
  sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
  vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
  penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
  laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
  tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
  neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
  volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
  pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
  lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>
```

```
body {
  width: 500px;
  margin: 0 auto;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}
```

```css
.positioned {
  position: sticky;
  top: 30px;
  left: 30px;
}
```

### Scrolling index

An interesting and common use of `position: sticky` is to create a scrolling index page where different headings stick to the top of the page as they reach it. The markup for such an example might look like so:

```html
<h1>Sticky positioning</h1>

<dl>
  <dt>A</dt>
  <dd>Apple</dd>
  <dd>Ant</dd>
  <dd>Altimeter</dd>
  <dd>Airplane</dd>
  <dt>B</dt>
  <dd>Bird</dd>
  <dd>Buzzard</dd>
  <dd>Bee</dd>
  <dd>Banana</dd>
  <dd>Beanstalk</dd>
  <dt>C</dt>
  <dd>Calculator</dd>
  <dd>Cane</dd>
  <dd>Camera</dd>
  <dd>Camel</dd>
  <dt>D</dt>
  <dd>Duck</dd>
  <dd>Dime</dd>
  <dd>Dipstick</dd>
  <dd>Drone</dd>
  <dt>E</dt>
  <dd>Egg</dd>
  <dd>Elephant</dd>
  <dd>Egret</dd>
</dl>
```

The CSS might look as follows. In normal flow the `<dt>` elements will scroll with the content. When we add `position: sticky` to the `<dt>` element, along with a `top` value of 0, supporting browsers will stick the headings to the top of the viewport as they reach that position. Each subsequent header will then replace the previous one as it scrolls up to that position.

```css
dt {
  background-color: black;
  color: white;
  padding: 10px;
  position: sticky;
  top: 0;
  left: 0;
  margin: 1em 0;
}
```

```
body {
  width: 500px;
  height: 1400px;
  margin: 0 auto;
}
```

```
<h1>Sticky positioning</h1>

<dl>
  <dt>A</dt>
  <dd>Apple</dd>
  <dd>Ant</dd>
  <dd>Altimeter</dd>
  <dd>Airplane</dd>
  <dt>B</dt>
  <dd>Bird</dd>
  <dd>Buzzard</dd>
  <dd>Bee</dd>
  <dd>Banana</dd>
  <dd>Beanstalk</dd>
  <dt>C</dt>
  <dd>Calculator</dd>
  <dd>Cane</dd>
  <dd>Camera</dd>
  <dd>Camel</dd>
  <dt>D</dt>
  <dd>Duck</dd>
  <dd>Dime</dd>
  <dd>Dipstick</dd>
  <dd>Drone</dd>
  <dt>E</dt>
  <dd>Egg</dd>
  <dd>Elephant</dd>
  <dd>Egret</dd>
</dl>
```

Sticky elements are "sticky" relative to the nearest ancestor with a "scrolling mechanism", which is determined by its ancestors' position property.

**Note:** You can see this example live at `7_sticky-positioning.html` (see source code).

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Positioning.

Summary
-------

I'm sure you had fun playing with basic positioning. While it's not an ideal method to use for entire layouts, there are many specific objectives it's suited for.

See also
--------

* The `position` property reference.
* Practical positioning examples, for some more useful ideas.
* Previous
* Overview: CSS layout
* Next


Supporting older browsers - Learn web development

Supporting older browsers
=========================

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2020.

* Learn more
* See full compatibility
* Report feedback
* Previous
* Overview: CSS layout
* Next

Visitors to your website may include users who either use older browsers or use browsers that do not support the CSS features you've implemented. This is a common scenario on the web, where new features are continuously being added to CSS. Browsers differ in their support for these features because different browsers tend to prioritize implementing different features. This article explains how you as a web developer can use modern web techniques to ensure that your website remains accessible to users with older technology.

|  |  |
| --- | --- |
| Prerequisites: |
 HTML basics (study
 Introduction to HTML), and an idea of how CSS works (study
 Introduction to CSS and
 Styling boxes.)
  |
| Objective: |
 To understand how to provide support for your layouts on older browsers
 that might not support the features you want to use.
  |

What is the browser landscape for your site?
--------------------------------------------

Every website is different in terms of its target audience. Before deciding on an approach, find out the number of visitors coming to your site using older browsers. This is straightforward if you're adding to or replacing an existing website, as you probably have analytics available that can tell you the technology your visitors are using. If you don't have analytics or you're launching a brand new site, then sites such as Statcounter can provide relevant statistics, which can be filtered by location.

You should also consider the type of devices and the way people use your site. For example, you can expect a higher-than-average usage of your website on mobile devices. Always prioritize accessibility and people using assistive technology; for some sites, this may be even more critical. Developers are often very worried about the experience of 1% of users, while overlooking the far greater number who have accessibility needs.

What is the support for the features you want to use?
-----------------------------------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

The above table is included at the bottom of every feature page under the section "Browser compatibility". After identifying the browsers your site visitors use, you can assess any technology that you want to use against how well it is supported across browsers and how easily you can provide an alternative for visitors who do not have that technology available.

On MDN, we provide browser compatibility information on every CSS property page. This compatibility information, presented in a table, includes a list of major browsers along with the versions that started supporting the property. The browser names take up the column headers. For example, take a look at the above table or the page for `grid-template-columns`, with special attention to the `subgrid` (most recently supported) and `masonry` (experimental and not supported) values.

These browser compatibility tables provide information on which browsers are compatible with the technology that you are looking for and the version from which the browser started supporting that functionality. Browser and mobile phone browser compatibility information are displayed separately.

Another popular way to find out about how well a feature is supported is the Can I Use website. This site lists the majority of Web Platform features with information about their browser support status. You can view usage statistics by location — useful if you work on a site that has users mostly for a specific area of the world. You can even link your Google Analytics account to get analysis based on your user data.

Understanding the technology your users have because of the browser they're using and the cross-browser support for features that you might want to use on your website, puts you in a good place to make all of your decisions and to know how best to support all of your users.

Feature support does not mean identical appearance
--------------------------------------------------

A website can't possibly look the same in all browsers. Some of your users will be viewing the site on a phone and others on a large desktop screen. Similarly, some of your users will have an old browser version, and others the latest browser. Some of your users might be hearing your content read out to them by a screen reader, while others might need to zoom in on the page to be able to read it. Supporting everyone means serving a version of your content that is designed defensively, so that it will look great on modern browsers, but will still be usable at a basic level for all users no matter how they are accessing your content.

A basic level of support comes from structuring your content well so that the normal flow of your page makes sense. For users on a limited data plan, their browsers might not load images, fonts, or even your CSS. However, the content should be presented in a way such that it is accessible and readable even when these elements are not fully loaded. A well-structured HTML document should always be your starting point. Ask yourself: *if you remove your stylesheet, does your content still make sense?*

It doesn't make commercial sense to spend time trying to give everyone an identical experience of your website. This is because user environments can vary widely and are beyond your control. There is a balance you need to strike between a plain HTML page and a fully featured website. It is helpful to test a plain, CSS-less view of your site to ensure that the fallback experience of your site is accessible. This fallback may never be viewed by people using very old or limited browsers, but may be viewed by your main target audience — users of modern browsers — when their browser or Internet connection fails temporarily. CSS simplifies creating these fallbacks. Therefore, it is better to focus on what you can control, that is, spend the time to make your site accessible, thereby serving more users.

Creating fallbacks in CSS
-------------------------

CSS specifications contain information that explain what the browser does when two similar features, such as layout methods, are applied to the same item. For example, they define what happens if an item is floated and is also a grid item and part of a CSS grid container. There is also a definition for what happens when an element has both `margin-top` and `margin-block-start` properties set.

When a browser doesn't recognize a new feature, it discards the declaration as invalid without throwing an error. Because browsers discard CSS properties and values they don't support, both old and new values can coexist in the same ruleset. Just make sure to declare the old value before the new value so that, when supported, the new value overwrites the old value (the fallback).

For example, most browsers support the two-value syntax of the `display` property. If a browser doesn't, it will use the older, single-value syntax.

```css
.container {
  display: inline-flex;
  display: inline flex;
}
```

Similarly, this error-handling ensures old CSS code bases continue to work even if legacy vendor-prefixed features are no longer supported. While vendor prefixing is no longer commonly used, if you must include a vendor-prefixed property or value, make sure to declare the prefixed value before the standard value so that, when supported, the new value overwrites the fallback value.

### Using new selectors

Including new selectors that aren't supported in all browsers needs to be handled more carefully. If a selector in a comma-separated list of selectors is invalid, the entire style block is ignored.

If using vendor-prefixed pseudo-elements or newpseudo-classes a browser may not yet support, include the prefixed values within a forgiving selector list by using `:is()` or `:where()` so the entire selector block doesn't get invalidated and ignored.

```css
:is(:-prefix-mistake, :unsupported-pseudo),
.valid {
  font-family: sans-serif;
}
:-prefix-mistake,
:unsupported-pseudo,
.valid {
  color: red;
}
```

In the above example, the `.valid` content will be `sans-serif` but not `red`.

Feature queries
---------------

Feature queries allow you to test whether a browser supports a particular CSS feature. This means that you can write some CSS for browsers that don't support a certain feature, then check to see if the browser has support and if so, throw in your fancy new features.

We can add a feature query to test for `subgrid` support, and provide styles based on that support:

```css
\* {
  box-sizing: border-box;
}

.wrapper {
  background-color: palegoldenrod;
  padding: 10px;
  max-width: 400px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.item {
  border-radius: 5px;
  background-color: rgb(207 232 220);
}

@supports (grid-template-rows: subgrid) {
  .wrapper {
    grid-template-rows: subgrid;
    gap: 10px;
    background-color: lightblue;
    text-align: center;
  }
}
```

```html
<div class="wrapper">
  <div class="item">Item One</div>
  <div class="item">Item Two</div>
  <div class="item">Item Three</div>
  <div class="item">Item Four</div>
  <div class="item">Item Five</div>
  <div class="item">Item Six</div>
</div>
```

Feature queries are supported in all modern browsers. Write your CSS for fully supported features first, outside of any feature queries. Once your site is usable and accessible to all users, add new features within feature query blocks. Browsers that support the feature queried can then render the newer CSS inside the feature query block. Use the approach of writing well-supported CSS first, then enhancing features based on support.

Testing older browsers
----------------------

One way is to use an online testing tool such as Sauce Labs, as detailed in the Cross browser testing module.

Summary
-------

You now have the knowledge to provide fallback CSS for older browsers and confidently test for new features. You should now feel confident making use of any new techniques that might come along.

Now that you have worked through our articles on CSS layout, it's time to test your comprehension with our assessment for the module: Fundamental layout comprehension.

See also
--------

* `@supports` at-rule
* CSS at-rules
* Using feature queries
* CSS conditional rules module
* Previous
* Overview: CSS layout
* Next


Test your skills: Grid - Learn web development

Test your skills: Grid
======================

The aim of this skill test is to assess whether you understand how a grid and grid items behave. You will be working through several small tasks that use different elements of the material you have just covered.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Task 1
------

In this task, you should create a grid into which the four child elements will auto-place. The grid should have three columns sharing the available space equally and a 20-pixel gap between the column and row tracks. After that, try adding more child containers inside the parent container with the class of `grid` and see how they behave by default.

Your final result should look like the image below:

![A three column grid with four items placed into it.](/en-US/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task1.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 2
------

In this task, we already have a grid defined. By editing the CSS rules for the two child elements, cause them to span over several grid tracks each. The second item should overlay the first as in the image below:

![A box with two items inside one overlaying the other.](/en-US/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task2.png)

Try updating the live code below to recreate the finished example:

Additional question:

* Can you now cause the first item to display on top without changing the order of items in the source?

Download the starting point for this task to work in your own editor or in an online editor.

Task 3
------

In this task, there are four direct children in this grid. The starting point has them displayed using auto-placement. Use the grid-area and grid-template-areas properties to lay the items out as shown in the image below:

![Four items displayed in a grid.](/en-US/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task3.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 4
------

In this task, you will need to use both grid layout and flexbox to recreate the example as seen in the image below. The gap between the column and row tracks should be 10px. You do not need to make any changes to the HTML in order to achieve this.

![Two rows of cards, each with an image and a set of tags.](/en-US/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task4.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.


Legacy layout methods - Learn web development

Legacy layout methods
=====================

* Previous
* Overview: CSS layout
* Next

Grid systems are a very common feature used in CSS layouts, and before CSS Grid Layout they tended to be implemented using floats or other layout features. You imagine your layout as a set number of columns (e.g. 4, 6, or 12), and then fit your content columns inside these imaginary columns. In this article we'll explore how these older methods work, in order that you understand how they were used if you work on an older project.

|  |  |
| --- | --- |
| Prerequisites: |
 HTML basics (study
 Introduction to HTML), and an idea of how CSS works (study
 Introduction to CSS and
 Styling boxes.)
  |
| Objective: |
 To understand the fundamental concepts behind the grid layout systems
 used prior to CSS Grid Layout being available in browsers.
  |

Layout and grid systems before CSS Grid Layout
----------------------------------------------

It may seem surprising to anyone coming from a design background that CSS didn't have an inbuilt grid system until very recently, and instead we seemed to be using a variety of sub-optimal methods to create grid-like designs. We now refer to these as "legacy" methods.

For new projects, in most cases CSS Grid Layout will be used in combination with one or more other modern layout methods to form the basis for any layout. You will however encounter "grid systems" using these legacy methods from time to time. It is worth understanding how they work, and why they are different to CSS Grid Layout.

This lesson will explain how grid systems and grid frameworks based on floats and flexbox work. Having studied Grid Layout you will probably be surprised how complicated this all seems! This knowledge will be helpful to you if you need to create fallback code for browsers that do not support newer methods, in addition to allowing you to work on existing projects which use these types of systems.

It is worth bearing in mind, as we explore these systems, that none of them actually create a grid in the way that CSS Grid Layout creates a grid. They work by giving items a size, and pushing them around to line them up in a way that *looks* like a grid.

A two column layout
-------------------

Let's start with the simplest possible example — a two column layout. You can follow along by creating a new `index.html` file on your computer, filling it with a simple HTML template, and inserting the below code into it at the appropriate places. At the bottom of the section you can see a live example of what the final code should look like.

First of all, we need some content to put into our columns. Replace whatever is inside the body currently with the following:

```html
<h1>2 column layout example</h1>
<div>
  <h2>First column</h2>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
    aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
    pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
    ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer
    ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur
    vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus.
    Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
    sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus.
    Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis,
    eget fermentum sapien.
  </p>
</div>

<div>
  <h2>Second column</h2>
  <p>
    Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
    ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
    est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
    tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies
    lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
    vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
    penatibus et magnis dis parturient montes, nascetur ridiculus mus.
  </p>
</div>
```

Each one of the columns needs an outer element to contain its content and let us manipulate all of it at once. In this example case we've chosen `<div>`s, but you could choose something more semantically appropriate like `<article>`s, `<section>`s, and `<aside>`, or whatever.

Now for the CSS. First, of all, apply the following to your HTML to provide some basic setup:

```css
body {
  width: 90%;
  max-width: 900px;
  margin: 0 auto;
}
```

The body will be 90% of the viewport wide until it gets to 900px wide, in which case it will stay fixed at this width and center itself in the viewport. By default, its children (the h1 and the two `<div>`s) will span 100% of the width of the body. If we want the two `<div>`s to be floated alongside one another, we need to set their widths to total 100% of the width of their parent element or smaller so they can fit alongside one another. Add the following to the bottom of your CSS:

```css
div:nth-of-type(1) {
  width: 48%;
}

div:nth-of-type(2) {
  width: 48%;
}
```

Here we've set both to be 48% of their parent's width — this totals 96%, leaving us 4% free to act as a gutter between the two columns, giving the content some space to breathe. Now we just need to float the columns, like so:

```css
div:nth-of-type(1) {
  width: 48%;
  float: left;
}

div:nth-of-type(2) {
  width: 48%;
  float: right;
}
```

Putting this all together should give us a result like so:

You'll notice here that we are using percentages for all the widths — this is quite a good strategy, as it creates a **liquid layout**, one that adjusts to different screen sizes and keeps the same proportions for the column widths at smaller screen sizes. Try adjusting the width of your browser window to see for yourself. This is a valuable tool for responsive web design.

**Note:** You can see this example running at 0\_two-column-layout.html (see also the source code).

Creating simple legacy grid frameworks
--------------------------------------

The majority of legacy frameworks use the behavior of the `float` property to float one column up next to another in order to create something that looks like a grid. Working through the process of creating a grid with floats shows you how this works and also introduces some more advanced concepts to build on the things you learned in the lesson on floats and clearing.

The easiest type of grid framework to create is a fixed width one — we just need to work out how much total width we want our design to be, how many columns we want, and how wide the gutters and columns should be. If we instead decided to lay out our design on a grid with columns that grow and shrink according to browser width, we would need to calculate percentage widths for the columns and gutters between them.

In the next sections we will look at how to create both. We will create a 12 column grid — a very common choice that is seen to be very adaptable to different situations given that 12 is nicely divisible by 6, 4, 3, and 2.

### A simple fixed width grid

Lets first create a grid system that uses fixed width columns.

Start out by making a local copy of our sample simple-grid.html file, which contains the following markup in its body.

```html
<div class="wrapper">
  <div class="row">
    <div class="col">1</div>
    <div class="col">2</div>
    <div class="col">3</div>
    <div class="col">4</div>
    <div class="col">5</div>
    <div class="col">6</div>
    <div class="col">7</div>
    <div class="col">8</div>
    <div class="col">9</div>
    <div class="col">10</div>
    <div class="col">11</div>
    <div class="col">12</div>
  </div>
  <div class="row">
    <div class="col span1">13</div>
    <div class="col span6">14</div>
    <div class="col span3">15</div>
    <div class="col span2">16</div>
  </div>
</div>
```

The aim is to turn this into a demonstration grid of two rows on a twelve column grid — the top row demonstrating the size of the individual columns, the second row some different sized areas on the grid.

![CSS grid with 16 grid items spread across twelve columns and two rows. The top row has 12 equal-width grid items in 12 columns. The second row has different-sized grid items. Item 13 spans 1 column, item 14 spans six columns, 15 spans three, and 16 spans two.](/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods/simple-grid-finished.png)

In the `<style>` element, add the following code, which gives the wrapper container a width of 980 pixels, with padding on the right-hand side of 20 pixels. This leaves us with 960 pixels for our total column/gutter widths — in this case, the padding is subtracted from the total content width because we have set `box-sizing` to `border-box` on all elements on the site (see The alternative CSS box model for more explanation).

```css
\* {
  box-sizing: border-box;
}

body {
  width: 980px;
  margin: 0 auto;
}

.wrapper {
  padding-right: 20px;
}
```

Now use the row container that is wrapped around each row of the grid to clear one row from another. Add the following rule below your previous one:

```css
.row {
  clear: both;
}
```

Applying this clearing means that we don't need to completely fill each row with elements making the full twelve columns. The rows will remain separated, and not interfere with each other.

The gutters between the columns are 20 pixels wide. We create these gutters as a margin on the left side of each column — including the first column, to balance out the 20 pixels of padding on the right-hand side of the container. So we have 12 gutters in total — 12 x 20 = 240.

We need to subtract that from our total width of 960 pixels, giving us 720 pixels for our columns. If we now divide that by 12, we know that each column should be 60 pixels wide.

Our next step is to create a rule for the class `.col`, floating it left, giving it a `margin-left` of 20 pixels to form the gutter, and a `width` of 60 pixels. Add the following rule to the bottom of your CSS:

```css
.col {
  float: left;
  margin-left: 20px;
  width: 60px;
  background: rgb(255 150 150);
}
```

The top row of single columns will now lay out neatly as a grid.

**Note:** We've also given each column a light red color so you can see exactly how much space each one takes up.

Layout containers that we want to span more than one column need to be given special classes to adjust their `width` values to the required number of columns (plus gutters in between). We need to create an additional class to allow containers to span 2 to 12 columns. Each width is the result of adding up the column width of that number of columns plus the gutter widths, which will always number one less than the number of columns.

Add the following at the bottom of your CSS:

```css
/\* Two column widths (120px) plus one gutter width (20px) \*/
.col.span2 {
  width: 140px;
}
/\* Three column widths (180px) plus two gutter widths (40px) \*/
.col.span3 {
  width: 220px;
}
/\* And so on… \*/
.col.span4 {
  width: 300px;
}
.col.span5 {
  width: 380px;
}
.col.span6 {
  width: 460px;
}
.col.span7 {
  width: 540px;
}
.col.span8 {
  width: 620px;
}
.col.span9 {
  width: 700px;
}
.col.span10 {
  width: 780px;
}
.col.span11 {
  width: 860px;
}
.col.span12 {
  width: 940px;
}
```

With these classes created we can now lay out different width columns on the grid. Try saving and loading the page in your browser to see the effects.

**Note:** If you are having trouble getting the above example to work, try comparing it against our finished version on GitHub (see it running live also).

Try modifying the classes on your elements or even adding and removing some containers, to see how you can vary the layout. For example, you could make the second row look like this:

```html
<div class="row">
  <div class="col span8">13</div>
  <div class="col span4">14</div>
</div>
```

Now you've got a grid system working, you can define the rows and the number of columns in each row, then fill each container with your required content. Great!

### Creating a fluid grid

Our grid works nicely, but it has a fixed width. We really want a flexible (fluid) grid that will grow and shrink with the available space in the browser viewport. To achieve this we can turn the reference pixel widths into percentages.

The equation that turns a fixed width into a flexible percentage-based one is as follows.
```

target / context = result
```

For our column width, our **target width** is 60 pixels and our **context** is the 960 pixel wrapper. We can use the following to calculate a percentage.
```

60 / 960 = 0.0625
```

We then move the decimal point 2 places giving us a percentage of 6.25%. So, in our CSS we can replace the 60 pixel column width with 6.25%.

We need to do the same with our gutter width:
```

20 / 960 = 0.02083333333
```

So we need to replace the 20 pixel `margin-left` on our `.col` rule and the 20 pixel `padding-right` on `.wrapper` with 2.08333333%.

#### Updating our grid

To get started in this section, make a new copy of your previous example page, or make a local copy of our simple-grid-finished.html code to use as a starting point.

Update the second CSS rule (with the `.wrapper` selector) as follows:

```css
body {
  width: 90%;
  max-width: 980px;
  margin: 0 auto;
}

.wrapper {
  padding-right: 2.08333333%;
}
```

Not only have we given it a percentage `width`, we have also added a `max-width` property in order to stop the layout becoming too wide.

Next, update the fourth CSS rule (with the `.col` selector) like so:

```css
.col {
  float: left;
  margin-left: 2.08333333%;
  width: 6.25%;
  background: rgb(255 150 150);
}
```

Now comes the slightly more laborious part — we need to update all our `.col.span` rules to use percentages rather than pixel widths. This takes a bit of time with a calculator; to save you some effort, we've done it for you below.

Update the bottom block of CSS rules with the following:

```css
/\* Two column widths (12.5%) plus one gutter width (2.08333333%) \*/
.col.span2 {
  width: 14.58333333%;
}
/\* Three column widths (18.75%) plus two gutter widths (4.1666666) \*/
.col.span3 {
  width: 22.91666666%;
}
/\* And so on… \*/
.col.span4 {
  width: 31.24999999%;
}
.col.span5 {
  width: 39.58333332%;
}
.col.span6 {
  width: 47.91666665%;
}
.col.span7 {
  width: 56.24999998%;
}
.col.span8 {
  width: 64.58333331%;
}
.col.span9 {
  width: 72.91666664%;
}
.col.span10 {
  width: 81.24999997%;
}
.col.span11 {
  width: 89.5833333%;
}
.col.span12 {
  width: 97.91666663%;
}
```

Now save your code, load it in a browser, and try changing the viewport width — you should see the column widths adjust nicely to suit.

**Note:** If you are having trouble getting the above example to work, try comparing it against our finished version on GitHub (see it running live also).

### Easier calculations using the calc() function

You could use the `calc()` function to do the math right inside your CSS — this allows you to insert simple mathematical equations into your CSS values, to calculate what a value should be. It is especially useful when there is complex math to be done, and you can even compute a calculation that uses different units, for example "I want this element's height to always be 100% of its parent's height, minus 50px". See this example from a MediaStream Recording API tutorial.

Anyway, back to our grids! Any column that spans more than one column of our grid has a total width of 6.25% multiplied by the number of columns spanned plus 2.08333333% multiplied by the number of gutters (which will always be the number of columns minus 1). The `calc()` function allows us to do this calculation right inside the width value, so for any item spanning 4 columns we can do this, for example:

```css
.col.span4 {
  width: calc((6.25% * 4) + (2.08333333% * 3));
}
```

Try replacing your bottom block of rules with the following, then reload it in the browser to see if you get the same result:

```css
.col.span2 {
  width: calc((6.25% * 2) + 2.08333333%);
}
.col.span3 {
  width: calc((6.25% * 3) + (2.08333333% * 2));
}
.col.span4 {
  width: calc((6.25% * 4) + (2.08333333% * 3));
}
.col.span5 {
  width: calc((6.25% * 5) + (2.08333333% * 4));
}
.col.span6 {
  width: calc((6.25% * 6) + (2.08333333% * 5));
}
.col.span7 {
  width: calc((6.25% * 7) + (2.08333333% * 6));
}
.col.span8 {
  width: calc((6.25% * 8) + (2.08333333% * 7));
}
.col.span9 {
  width: calc((6.25% * 9) + (2.08333333% * 8));
}
.col.span10 {
  width: calc((6.25% * 10) + (2.08333333% * 9));
}
.col.span11 {
  width: calc((6.25% * 11) + (2.08333333% * 10));
}
.col.span12 {
  width: calc((6.25% * 12) + (2.08333333% * 11));
}
```

**Note:** You can see our finished version in fluid-grid-calc.html (also see it live).

### Semantic versus "unsemantic" grid systems

Adding classes to your markup to define layout means that your content and markup becomes tied to your visual presentation. You will sometimes hear this use of CSS classes described as being "unsemantic" — describing how the content looks — rather than a semantic use of classes that describes the content. This is the case with our `span2`, `span3`, etc., classes.

These are not the only approach. You could instead decide on your grid and then add the sizing information to the rules for existing semantic classes. For example, if you had a `<div>` with a class of `content` on it that you wanted to span 8 columns, you could copy across the width from the `span8` class, giving you a rule like so:

```css
.content {
  width: calc((6.25% * 8) + (2.08333333% * 7));
}
```

**Note:** If you were to use a preprocessor such as Sass, you could create a simple mixin to insert that value for you.

### Enabling offset containers in our grid

The grid we have created works well as long as we want to start all of the containers flush with the left-hand side of the grid. If we wanted to leave an empty column space before the first container — or between containers — we would need to create an offset class to add a left margin to our site to push it across the grid visually. More math!

Let's try this out.

Start with your previous code, or use our fluid-grid.html file as a starting point.

Let's create a class in our CSS that will offset a container element by one column width. Add the following to the bottom of your CSS:

```css
.offset-by-one {
  margin-left: calc(6.25% + (2.08333333% * 2));
}
```

Or if you prefer to calculate the percentages yourself, use this one:

```css
.offset-by-one {
  margin-left: 10.41666666%;
}
```

You can now add this class to any container you want to leave a one column wide empty space on the left-hand side of it. For example, if you have this in your HTML:

```html
<div class="col span6">14</div>
```

Try replacing it with

```html
<div class="col span5 offset-by-one">14</div>
```

**Note:** Notice that you need to reduce the number of columns spanned, to make room for the offset!

Try loading and refreshing to see the difference, or check out our fluid-grid-offset.html example (see it running live also). The finished example should look like this:

![The grid has 2 rows. The first row has 12 equal-width grid items and the second row has 4 items of different widths. Item 13 spans 1 column, item 14 spans five columns, 15 spans three, and 16 spans two. Item 14 has the 'offset-by-one' class applied, which means it starts in the 3rd column, rather than the second, leaving a one-column wide empty space in the second-row second-column. ](/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods/offset-grid-finished.png)

**Note:** As an extra exercise, can you implement an `offset-by-two` class?

### Floated grid limitations

When using a system like this you do need to take care that your total widths add up correctly, and that you don't include elements in a row that span more columns than the row can contain. Due to the way floats work, if the number of grid columns becomes too wide for the grid, the elements on the end will drop down to the next line, breaking the grid.

Also bear in mind that if the content of the elements gets wider than the rows they occupy, it will overflow and look a mess.

The biggest limitation of this system is that it is essentially one dimensional. We are dealing with columns, and spanning elements across columns, but not rows. It is very difficult with these older layout methods to control the height of elements without explicitly setting a height, and this is a very inflexible approach too — it only works if you can guarantee that your content will be a certain height.

Flexbox grids?
--------------

If you read our previous article about flexbox, you might think that flexbox is the ideal solution for creating a grid system. There are many flexbox-based grid systems available and flexbox can solve many of the issues that we've already discovered when creating our grid above.

However, flexbox was never designed as a grid system and poses a new set of challenges when used as one. As a simple example of this, we can take the same example markup we used above and use the following CSS to style the `wrapper`, `row`, and `col` classes:

```css
body {
  width: 90%;
  max-width: 980px;
  margin: 0 auto;
}

.wrapper {
  padding-right: 2.08333333%;
}

.row {
  display: flex;
}

.col {
  margin-left: 2.08333333%;
  margin-bottom: 1em;
  width: 6.25%;
  flex: 1 1 auto;
  background: rgb(255 150 150);
}
```

You can try making these replacements in your own example, or look at our flexbox-grid.html example code (see it running live also).

Here we are turning each row into a flex container. With a flexbox-based grid we still need rows in order to allow us to have elements that add up to less than 100%. We set that container to `display: flex`.

On `.col` we set the `flex` property's first value (`flex-grow`) to 1 so our items can grow, the second value (`flex-shrink`) to 1 so the items can shrink, and the third value (`flex-basis`) to `auto`. As our element has a `width` set, `auto` will use that width as the `flex-basis` value.

On the top line we get twelve neat boxes on the grid and they grow and shrink equally as we change the viewport width. On the next line, however, we only have four items and these also grow and shrink from that 60px basis. With only four of them they can grow a lot more than the items in the row above, the result being that they all occupy the same width on the second row.

![The grid has two rows. Each row is a flex container. The first row has twelve equal-width flex items. The second row has four equal-width flex items.](/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods/flexbox-grid-incomplete.png)

To fix this we still need to include our `span` classes to provide a width that will replace the value used by `flex-basis` for that element.

They also don't respect the grid used by the items above because they don't know anything about it.

Flexbox is **one-dimensional** by design. It deals with a single dimension, that of a row or a column. We can't create a strict grid for columns and rows, meaning that if we are to use flexbox for our grid, we still need to calculate percentages as for the floated layout.

In your project you might still choose to use a flexbox 'grid' due to the additional alignment and space distribution capabilities flexbox provides over floats. You should, however, be aware that you are still using a tool for something other than what it was designed for. So you may feel like it is making you jump through additional hoops to get the end result you want.

Third party grid systems
------------------------

Now that we understand the math behind our grid calculations, we are in a good place to look at some of the third party grid systems in common use. If you search for "CSS Grid framework" on the Web, you will find a huge list of options to choose from. Popular frameworks such as Bootstrap and Foundation include a grid system. There are also standalone grid systems, either developed using CSS or using preprocessors.

Let's take a look at one of these standalone systems as it demonstrates common techniques for working with a grid framework. The grid we will be using is part of Skeleton, a simple CSS framework.

To get started visit the Skeleton website, and choose "Download" to download the ZIP file. Unzip this and copy the skeleton.css and normalize.css files into a new directory.

Make a copy of our html-skeleton.html file and save it in the same directory as the skeleton and normalize CSS.

Include the skeleton and normalize CSS in the HTML page, by adding the following to its head:

```html
<link href="normalize.css" rel="stylesheet" />
<link href="skeleton.css" rel="stylesheet" />
```

Skeleton includes more than a grid system — it also contains CSS for typography and other page elements that you can use as a starting point. We'll leave these at the defaults for now, however — it's the grid we are really interested in here.

**Note:** Normalize is a really useful little CSS library written by Nicolas Gallagher, which automatically does some useful basic layout fixes and makes default element styling more consistent across browsers.

We will use similar HTML to our earlier example. Add the following into your HTML body:

```html
<div class="container">
  <div class="row">
    <div class="col">1</div>
    <div class="col">2</div>
    <div class="col">3</div>
    <div class="col">4</div>
    <div class="col">5</div>
    <div class="col">6</div>
    <div class="col">7</div>
    <div class="col">8</div>
    <div class="col">9</div>
    <div class="col">10</div>
    <div class="col">11</div>
    <div class="col">12</div>
  </div>
  <div class="row">
    <div class="col">13</div>
    <div class="col">14</div>
    <div class="col">15</div>
    <div class="col">16</div>
  </div>
</div>
```

To start using Skeleton we need to give the wrapper `<div>` a class of `container` — this is already included in our HTML. This centers the content with a maximum width of 960 pixels. You can see how the boxes now never become wider than 960 pixels.

You can take a look in the skeleton.css file to see the CSS that is used when we apply this class. The `<div>` is centered using `auto` left and right margins, and a padding of 20 pixels is applied left and right. Skeleton also sets the `box-sizing` property to `border-box` like we did earlier, so the padding and borders of this element will be included in the total width.

```css
.container {
  position: relative;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}
```

Elements can only be part of the grid if they are inside a row, so as with our earlier example we need an additional `<div>` or other element with a class of `row` nested between the content `<div>` elements and the container `<div>`. We've done this already as well.

Now let's lay out the container boxes. Skeleton is based on a 12 column grid. The top line boxes all need classes of `one column` to make them span one column.

Add these now, as shown in the following snippet:

```html
<div class="container">
  <div class="row">
    <div class="one column">1</div>
    <div class="one column">2</div>
    <div class="one column">3</div>
    /* and so on */
  </div>
</div>
```

Next, give the containers on the second row classes explaining the number of columns they should span, like so:

```html
<div class="row">
  <div class="one column">13</div>
  <div class="six columns">14</div>
  <div class="three columns">15</div>
  <div class="two columns">16</div>
</div>
```

Try saving your HTML file and loading it in your browser to see the effect.

**Note:** If you are having trouble getting this example to work, try widening the window you're using to view it (the grid won't be displayed as described here if the window is too narrow). If that doesn't work, try comparing it to our html-skeleton-finished.html file (see it running live also).

If you look in the skeleton.css file you can see how this works. For example, Skeleton has the following defined to style elements with "three columns" classes added to them.

```css
.three.columns {
  width: 22%;
}
```

All Skeleton (or any other grid framework) is doing is setting up predefined classes that you can use by adding them to your markup. It's exactly the same as if you did the work of calculating these percentages yourself.

As you can see, we need to write very little CSS when using Skeleton. It deals with all of the floating for us when we add classes to our markup. It is this ability to hand responsibility for layout over to something else that made using a framework for a grid system a compelling choice! However these days, with CSS Grid Layout, many developers are moving away from these frameworks to use the inbuilt native grid that CSS provides.

Summary
-------

You now understand how various grid systems are created, which will be useful in working with older sites and in understanding the difference between the native grid of CSS Grid Layout and these older systems.

* Previous
* Overview: CSS layout
* Next


Test your skills: Floats - Learn web development

Test your skills: Floats
========================

The aim of this skill test is to assess whether you understand floats in CSS using the `float` and `clear` properties and values as well as other methods for clearing floats. You will be working through three small tasks that use different elements of the material you have just covered.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Task 1
------

In this task, you need to float the two elements with a class of `float1` and `float2` left and right, respectively. The text should then appear between the two boxes, as in the image below:

![Two blocks displaying left and right of some text.](/en-US/docs/Learn/CSS/CSS_layout/Floats_skills/float-task1.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 2
------

In this task, the element with a class of `float` should be floated left. Then we want the first line of text to display next to that element, but the following line of text (which has a class of `below`) to display underneath it.

Your final result should look like the image below:

![A box displayed to the left of a line of text, with some more text below.](/en-US/docs/Learn/CSS/CSS_layout/Floats_skills/float-task2.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 3
------

In this task, we have a floated element. The box wrapping the float and text is displaying behind the float. Use the most up-to-date method available to cause the box background to extend to below the float, as in the image below:

![A block displayed to the right of some text both wrapped by a box with a background color.](/en-US/docs/Learn/CSS/CSS_layout/Floats_skills/float-task3.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.


Test your skills: Multicol - Learn web development

Test your skills: Multicol
==========================

The aim of this skill test is to assess whether you understand CSS multiple-column layout, including the `column-count`, `column-width`, `column-gap`, `column-span` and `column-rule` properties and values. You will be working through three small tasks that use different elements of the material you have just covered.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

Task 1
------

In this task, we want you to create three columns, with a 50px gap between each column.

Your final result should look like the image below:

![Three columns of text](/en-US/docs/Learn/CSS/CSS_layout/Multicol_skills/multicol-task1.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 2
------

In this task, we want you to create columns which have a minimum width of 200px. Then, add a 5px grey rule between each column, ensuring there is 10px of space between the edge of the rule and the column content.

Your final result should look like the image below:

![Three columns of text with a grey rule between them.](/en-US/docs/Learn/CSS/CSS_layout/Multicol_skills/multicol-task2.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

Task 3
------

In this task, we want you to cause the element containing the heading and subheading to span across all columns so it looks like the image below:

![Three columns of text with a heading and subheading spanning all three in the middle.](/en-US/docs/Learn/CSS/CSS_layout/Multicol_skills/multicol-task3.png)

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.


Flexbox - Learn web development

Flexbox
=======

* Previous
* Overview: CSS layout
* Next

Flexbox is a one-dimensional layout method for arranging items in rows or columns. Items *flex* (expand) to fill additional space or shrink to fit into smaller spaces. This article explains all the fundamentals.

|  |  |
| --- | --- |
| Prerequisites: |
 HTML basics (study
 Introduction to HTML), and an idea of how CSS works (study
 Introduction to CSS.)
  |
| Objective: | To learn how to use the Flexbox layout system to create web layouts. |

Why Flexbox?
------------

For a long time, the only reliable cross-browser compatible tools available for creating CSS layouts were features like floats and positioning. These work, but in some ways they're also limiting and frustrating.

The following simple layout designs are either difficult or impossible to achieve with such tools in any kind of convenient, flexible way:

* Vertically centering a block of content inside its parent.
* Making all the children of a container take up an equal amount of the available width/height, regardless of how much width/height is available.
* Making all columns in a multiple-column layout adopt the same height even if they contain a different amount of content.

As you'll see in subsequent sections, flexbox makes a lot of layout tasks much easier. Let's dig in!

Introducing a simple example
----------------------------

In this article, you'll work through a series of exercises to help you understand how flexbox works. To get started, you should make a local copy of the first starter file — flexbox0.html from our GitHub repo. Load it in a modern browser (like Firefox or Chrome) and have a look at the code in your code editor. You can also see it live here.

![Image showing the starting point of Flexbox tutorial](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/bih741v.png)

You'll see that we have a `<header>` element with a top level heading inside it and a `<section>` element containing three `<article>`s. We're going to use these to create a fairly standard three column layout.

Specifying what elements to lay out as flexible boxes
-----------------------------------------------------

To start with, we need to select which elements are to be laid out as flexible boxes. To do this, we set a special value of `display` on the parent element of the elements you want to affect. In this case we want to lay out the `<article>` elements, so we set this on the `<section>`:

```css
section {
  display: flex;
}
```

This causes the `<section>` element to become a **flex container** and its children become **flex items**. This is what it looks like:

![A two row container that includes a single column in the first row and a 3-column layout in the second row that shows how a webpage can be divided into different layouts depending on the contents](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example2.png)

This single declaration gives us everything we need. Incredible, right? We have a multiple column layout with equal-sized columns, and the columns are all the same height. This is because the default values given to flex items (the children of the flex container) are set up to solve common problems such as this.

Let's recap what's happening here. Adding a `display` value of `flex` to an element makes it a flex container. The container is displayed as Block-level content in terms of how it interacts with the rest of the page. When the element is converted to a flex container, its children are converted to (and laid out as) flex items.

 You can make the container inline using an outside `display` value (e.g., `display: inline flex`), which affects how the container itself is laid out in the page.
 The legacy `inline-flex` display value displays the container as inline as well.
 We'll focus on how the contents of the container behave in this tutorial, but if you want to see the effect of inline versus block layout, you can have a look at the value comparison on the `display` property page.

The next sections explain in more detail what flex items are and what happens inside an element when you make it a flex container.

The flex model
--------------

When elements are laid out as flex items, they are laid out along two axes:

![Three flex items in a left-to-right language are laid out side-by-side in a flex container. The main axis — the axis of the flex container in the direction in which the flex items are laid out — is horizontal. The ends of the axis are main-start and main-end and are on the left and right respectively. The cross axis is vertical; perpendicular to the main axis. The cross-start and cross-end are at the top and bottom respectively. The length of the flex item along the main axis, in this case, the width, is called the main size, and the length of the flex item along the cross axis, in this case, the height, is called the cross size.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flex_terms.png)

* The **main axis** is the axis running in the direction the flex items are laid out in (for example, as a row across the page, or a column down the page.) The start and end of this axis are called the **main start** and **main end**.
* The **cross axis** is the axis running perpendicular to the direction the flex items are laid out in. The start and end of this axis are called the **cross start** and **cross end**.
* The parent element that has `display: flex` set on it (the `<section>` in our example) is called the **flex container**.
* The items laid out as flexible boxes inside the flex container are called **flex items** (the `<article>` elements in our example).

Bear this terminology in mind as you go through subsequent sections. You can always refer back to it if you get confused about any of the terms being used.

Columns or rows?
----------------

Flexbox provides a property called `flex-direction` that specifies which direction the main axis runs (which direction the flexbox children are laid out in). By default this is set to `row`, which causes them to be laid out in a row in the direction your browser's default language works in (left to right, in the case of an English browser).

Try adding the following declaration to your `<section>` rule:

```css
flex-direction: column;
```

You'll see that this puts the items back in a column layout, much like they were before we added any CSS. Before you move on, delete this declaration from your example.

**Note:** You can also lay out flex items in a reverse direction using the `row-reverse` and `column-reverse` values. Experiment with these values too!

Wrapping
--------

One issue that arises when you have a fixed width or height in your layout is that eventually your flexbox children will overflow their container, breaking the layout. Have a look at our flexbox-wrap0.html example and try viewing it live (take a local copy of this file now if you want to follow along with this example):

![The Sample flexbox example has all the flex items laid out in a single row of the flex container. The eighth flex item overflows the browser window, and the page has visible horizontal and vertical scroll bars as it cannot be accommodated within the width of the window as the previous seven flex items have taken the space available within the viewport. By default, the Browser tries to place all the flex items in a single row if the flex-direction is set to row or a single column if the flex-direction is set to column.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example3.png)

Here we see that the children are indeed breaking out of their container. One way in which you can fix this is to add the following declaration to your `<section>` rule:

```css
flex-wrap: wrap;
```

Also, add the following declaration to your `<article>` rule:

```css
flex: 200px;
```

Try this now. You'll see that the layout looks much better with this included:

![Flex items are laid out in multiple rows in the flex container. The flex-wrap property is set to 'wrap' in the flex container which displays the flex items in a new row if the flex items in the previous row overflow outside the flexbox container. Each flex item is given a width of 200 pixels. All the items are stretched to be the same height, as tall as the flex item with the most content.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example4.png)

We now have multiple rows. Each row has as many flexbox children fitted into it as is sensible. Any overflow is moved down to the next line. The `flex: 200px` declaration set on the articles means that each will be at least 200px wide. We'll discuss this property in more detail later on. You might also notice that the last few children on the last row are each made wider so that the entire row is still filled.

But there's more we can do here. First of all, try changing your `flex-direction` property value to `row-reverse`. Now you'll see that you still have your multiple row layout, but it starts from the opposite corner of the browser window and flows in reverse.

flex-flow shorthand
-------------------

At this point it's worth noting that a shorthand exists for `flex-direction` and `flex-wrap`: `flex-flow`. So, for example, you can replace

```css
flex-direction: row;
flex-wrap: wrap;
```

with

```css
flex-flow: row wrap;
```

Flexible sizing of flex items
-----------------------------

Let's now return to our first example and look at how we can control what proportion of space flex items take up compared to the other flex items. Fire up your local copy of flexbox0.html, or take a copy of flexbox1.html as a new starting point (see it live).

First, add the following rule to the bottom of your CSS:

```css
article {
  flex: 1;
}
```

This is a unitless proportion value that dictates how much available space along the main axis each flex item will take up compared to other flex items. In this case, we're giving each `<article>` element the same value (a value of 1), which means they'll all take up an equal amount of the spare space left after properties like padding and margin have been set. This value is proportionally shared among the flex items: giving each flex item a value of 400000 would have exactly the same effect.

Now add the following rule below the previous one:

```css
article:nth-of-type(3) {
  flex: 2;
}
```

Now when you refresh, you'll see that the third `<article>` takes up twice as much of the available width as the other two. There are now four proportion units available in total (since 1 + 1 + 2 = 4). The first two flex items have one unit each, so they each take 1/4 of the available space. The third one has two units, so it takes up 2/4 of the available space (or one-half).

You can also specify a minimum size value within the flex value. Try updating your existing article rules like so:

```css
article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}
```

This basically states, "Each flex item will first be given 200px of the available space. After that, the rest of the available space will be shared according to the proportion units." Try refreshing and you'll see a difference in how the space is shared.

![The Sample flexbox example flex container has three flex items. All the flex items have a minimum width of 200 pixels—set using 'flex'. The value of flex for first two flex items is 1 and for the third item is 2. This splits the remaining space in the flex container into 4 proportion units. One unit is assigned to each of the first two flex items and 2 units are assigned to the third flex item, making the third flex item wider than the other two, which are of the same width.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example1.png)

The real value of flexbox can be seen in its flexibility/responsiveness. If you resize the browser window or add another `<article>` element, the layout continues to work just fine.

flex: shorthand versus longhand
-------------------------------

`flex` is a shorthand property that can specify up to three different values:

* The unitless proportion value we discussed above. This can be specified separately using the `flex-grow` longhand property.
* A second unitless proportion value, `flex-shrink`, which comes into play when the flex items are overflowing their container. This value specifies how much an item will shrink in order to prevent overflow. This is quite an advanced flexbox feature and we won't be covering it any further in this article.
* The minimum size value we discussed above. This can be specified separately using the `flex-basis` longhand value.

We'd advise against using the longhand flex properties unless you really have to (for example, to override something previously set). They lead to a lot of extra code being written, and they can be somewhat confusing.

Horizontal and vertical alignment
---------------------------------

You can also use flexbox features to align flex items along the main or cross axis. Let's explore this by looking at a new example: flex-align0.html (see it live also). We're going to turn this into a neat, flexible button/toolbar. At the moment you'll see a horizontal menu bar with some buttons jammed into the top left-hand corner.

![Five buttons with labels Smile, Laugh, Wink, Shrug and Blush are laid out in a row in a flex container. The buttons are jammed into the top left-hand corner that doesn't look neat.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example5.png)

First, take a local copy of this example.

Now, add the following to the bottom of the example's CSS:

```css
div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}
```

![Five buttons with labels Smile, Laugh, Wink, Shrug & Blush are laid out in a row in a flex container. The flex items are positioned at the center of the cross-axis by setting the align-items property to center. The flex items are spaced evenly along the main-axis by setting the justify-content property to space-around.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox_center_space-around.png)

Refresh the page and you'll see that the buttons are now nicely centered horizontally and vertically. We've done this via two new properties.

`align-items` controls where the flex items sit on the cross axis.

* By default, the value is `stretch`, which stretches all flex items to fill the parent in the direction of the cross axis. If the parent doesn't have a fixed height in the cross axis direction, then all flex items will become as tall as the tallest flex item. This is how our first example had columns of equal height by default.
* The `center` value that we used in our above code causes the items to maintain their intrinsic dimensions, but be centered along the cross axis. This is why our current example's buttons are centered vertically.
* You can also have values like `flex-start` and `flex-end`, which will align all items at the start and end of the cross axis respectively. See `align-items` for the full details.

You can override the `align-items` behavior for individual flex items by applying the `align-self` property to them. For example, try adding the following to your CSS:

```css
button:first-child {
  align-self: flex-end;
}
```

![Five buttons with labels Smile, Laugh, Wink, Shrug & Blush are laid out in a row in a flex container. All the flex items except the first one are positioned at the center of the cross-axis, or vertically centered, by setting the align-items property to center. The first item is flush against the bottom of the flex container, at the end of the cross-axis, with the align-self property set to flex-end. The flex items are spaced evenly along the main-axis, or width, of the container.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox_first-child_flex-end.png)

Have a look at what effect this has and remove it again when you've finished.

`justify-content` controls where the flex items sit on the main axis.

* The default value is `flex-start`, which makes all the items sit at the start of the main axis.
* You can use `flex-end` to make them sit at the end.
* `center` is also a value for `justify-content`. It'll make the flex items sit in the center of the main axis.
* The value we've used above, `space-around`, is useful — it distributes all the items evenly along the main axis with a bit of space left at either end.
* There is another value, `space-between`, which is very similar to `space-around` except that it doesn't leave any space at either end.

The `justify-items` property is ignored in flexbox layouts.

We'd like to encourage you to play with these values to see how they work before you continue.

Ordering flex items
-------------------

Flexbox also has a feature for changing the layout order of flex items without affecting the source order. This is another thing that is impossible to do with traditional layout methods.

The code for this is simple. Try adding the following CSS to your button bar example code:

```css
button:first-child {
  order: 1;
}
```

Refresh and you'll see that the "Smile" button has moved to the end of the main axis. Let's talk about how this works in a bit more detail:

* By default, all flex items have an `order` value of 0.
* Flex items with higher specified order values will appear later in the display order than items with lower order values.
* Flex items with the same order value will appear in their source order. So if you have four items whose order values have been set as 2, 1, 1, and 0 respectively, their display order would be 4th, 2nd, 3rd, then 1st.
* The 3rd item appears after the 2nd because it has the same order value and is after it in the source order.

You can set negative order values to make items appear earlier than items whose value is 0. For example, you could make the "Blush" button appear at the start of the main axis using the following rule:

```css
button:last-child {
  order: -1;
}
```

Nested flex boxes
-----------------

It's possible to create some pretty complex layouts with flexbox. It's perfectly OK to set a flex item to also be a flex container, so that its children are also laid out like flexible boxes. Have a look at complex-flexbox.html (see it live also).

![The Sample flexbox example has three flex item children laid out in a row. The first two are the same width, the third is slightly wider. The third flex item is also a flex container. It has a set of buttons in two rows followed by text. The first row of buttons has 4 buttons that are laid out in a row; the buttons are the same width, taking up the full width of the container. The second row has a single button that takes up the entire width of the row on its own. This complex layout where few flex items are treated as flex containers.](/en-US/docs/Learn/CSS/CSS_layout/Flexbox/flexbox-example7.png)

The HTML for this is fairly simple. We've got a `<section>` element containing three `<article>`s. The third `<article>` contains three `<div>`s, and the first `<div>` contains five `<button>`s:
```

section - article
          article
          article - div - button
                    div   button
                    div   button
                          button
                          button
```

Let's look at the code we've used for the layout.

First of all, we set the children of the `<section>` to be laid out as flexible boxes.

```css
section {
  display: flex;
}
```

Next, we set some flex values on the `<article>`s themselves. Take special note of the second rule here: we're setting the third `<article>` to have its children laid out like flex items too, but this time we're laying them out like a column.

```css
article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}
```

Next, we select the first `<div>`. We first use `flex: 1 100px;` to effectively give it a minimum height of 100px, then we set its children (the `<button>` elements) to also be laid out like flex items. Here we lay them out in a wrapping row and align them in the center of the available space as we did with the individual button example we saw earlier.

```css
article:nth-of-type(3) div:first-child {
  flex: 1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}
```

Finally, we set some sizing on the button. This time by giving it a flex value of 1 auto. This has a very interesting effect, which you'll see if you try resizing your browser window width. The buttons will take up as much space as they can. As many will fit on a line as is comfortable; beyond that, they'll drop to a new line.

```css
button {
  flex: 1 auto;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}
```

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Flexbox.

Summary
-------

That concludes our tour of the basics of Flexbox. We hope you had fun and will have a good play around with it as you proceed further with your learning. Next, we'll have a look at another important aspect of CSS layouts: CSS Grids.

See also
--------

* CSS-Tricks Guide to Flexbox — an article explaining everything about Flexbox in a visually appealing way
* Flexbox Froggy — an educational game to learn and better understand the basics of Flexbox
* Previous
* Overview: CSS layout
* Next