DEV Community

Cover image for Exploring the CSS display property: A deep dive
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

Exploring the CSS display property: A deep dive

Written by Ibadehin Mojeed✏️

HTML elements typically follow the standard flow layout — also called “normal flow” — and naturally arrange themselves on the page. In this flow layout, some elements expand to fill their entire parent container and stack vertically, one above the other. Others only occupy the space needed for their content.

These different behaviors arise from the default display property assigned to these elements. In this lesson, we'll dive into the CSS display property. We’ll examine its various values in detail with examples and code snippets to illustrate how each value can be utilized.

What is CSS display property?

The CSS display property specifies an element’s outer and inner display values:

  • Outer display value: Determines whether its box takes up the full width of its parent container or gets sized based on its content
  • Inner display value: Controls the layout of the element’s children — that is, whether they adhere to normal flow or follow other layout options

The display property also manages whether the element generates any box at all.

The display syntax

The syntax for the CSS display property is as follows:

element {
   display: value;
}
Enter fullscreen mode Exit fullscreen mode

You can use different values to adjust the element’s outer and inner display behavior. Keywords that affect the outer display include:

  • block: The element fills the entire width of its container. Each new element appears on a new line unless otherwise specified
  • inline: The element is sized according to its content. Each new element appears on the same line unless otherwise specified, and will wrap to the next line if there is not enough horizontal space in the parent container

Meanwhile, keywords that affect the inner display include:

  • flow: The default layout model for elements participating in the normal document flow. Elements are laid out according to their type (block-level or inline)
  • flow-root: Creates a new block formatting context, causing the element's children to be laid out using the normal flow while preventing margin collapse with other elements
  • flex: Establishes a flex container, ensuring the element's direct children (flex items) participate in a flexible box layout
  • grid: Establishes a grid container, ensuring the element's direct children (grid items) are positioned into a grid defined by rows and columns
  • table: Ensures the element behaves like a <table>, and that its children behave like table-related elements (<caption>, <tbody>, <thead>, <tfoot>, <tr>, <th>, <td>)

In the coming sections, we’ll discuss the various display values available and how to use them strategically in your web projects. We’ll also explore using multiple display property values to specify both the outer and inner display.

The default display values: block and inline

Before we start to apply display values explicitly on elements, the CodePen below demonstrates how some elements are displayed by default. We added background colors to make the example elements stand out individually.

See this example on CodePen.

We’ll use this example to explore the block and inline values in more detail.

Block-level elements

In the CodePen above, you can see that the example <section>, <div>, <p>, and <footer> elements fill the entire width of their container, each appearing on a new line. These types of elements are called block-level elements, and by default have a display value of block:

element {
  display: block;
}
Enter fullscreen mode Exit fullscreen mode

Other block-level elements include <article>, <aside>, <table>, <form>, and more.

Setting the display property‘s value to block can turn a non-block element into a block-level element.

In addition, block-level elements can accommodate other block-level elements and inline elements. We can adjust various properties for block-level elements, including their height, width, margins, and padding. They are often used to structure webpage layouts, create text content, list, and so on.

Inline elements

Elements like <span> and <a> — which you can also see in the CodePen above — only occupy the space required by their content, and they don’t push other elements away. These elements are called inline elements, and they have a display value of inline by default:

element {
  display: inline;
}
Enter fullscreen mode Exit fullscreen mode

Other inline elements include <img>, <button>, <strong>, <input>, <textarea>, and more. They’re useful when you need elements to appear in line with text without causing line breaks. Setting the display property’s value to inline transforms a non-inline element into an inline element. Inline elements can’t contain block-level elements, but can accommodate other inline elements.

Although inline elements typically don’t accept height and width properties, exceptions like the <img> element exist. Applying padding to inline elements doesn't push other elements away, as shown in the CodePen example, and margins only affect horizontal displacement.

We can target any of these elements in the flow layout and use the display property to change their default display values.

Using multiple display property values in CSS

As we mentioned earlier, an element’s display property defines both its outer and inner display types. Previously, we could only use a single keyword for this property’s value, as demonstrated above. However, in most cases, this syntax lacks an explicit description of its functionality.

For instance, display: block; or display: inline; solely defines the element’s outer display type — that is, whether the element takes up its container’s full width or gets sized based on its content. It doesn’t specify the inner display type, although the default layout behavior for the children is implied, meaning they follow the normal flow.

Note that in the CodePen above, the <section> element’s children are also laid out in the normal flow, following the expected default behavior as block and inline boxes.

Since the display property’s Level 3 Specification was released, we can now utilize two keywords to specify both the outer and inner display values. The syntax is as follows:

element {
  display: outer-value inner-value;
}
Enter fullscreen mode Exit fullscreen mode

In many cases, using a multi-keyword value will result in the same behavior as a single value. The multi-keyword values simply provide clarity by defining both the outer and inner display values. For example, in the earlier CSS specification, we might use the single-keyword value block in our display property:

element {
  display: block;
}
Enter fullscreen mode Exit fullscreen mode

However, it’s now recommended to use the multi-keyword value block flow to be more explicit:

element {
  display: block flow;
}
Enter fullscreen mode Exit fullscreen mode

This will convey the actual meaning of the display value more clearly, although it won’t change the expected behavior.

Here’s a table summarizing how to take a single display property used in older CSS specifications and rewrite it using the more explicit syntax recommended in the Level 3 specification:

Old syntax New syntax
display: block; display: block flow;
display: inline; display: inline flow;
display: flex; display: block flex;
display: grid; display: block grid;
display: flow-root; display: block flow-root;
display: table; display: block table;
display: inline-flex; display: inline flex;
display: inline-grid; display: inline grid;
display: inline-block; display: inline flow-root;

Note that inline-flex and inline-grid are single-keyword display values used in earlier CSS specifications. The updated syntax recommended in the Level 3 specification replaces the hyphen with a space, making them multi-keyword display values.

Similarly, inline-block is a single keyword that creates a block formatting context (BFC) on an inline element. It’s now called inline flow-root, allowing us to use the inner display value of flow-root to create a BFC on an inline box. Using both the outer and inner value types enables us to immediately understand the role of an element in the normal flow and the layout used for its children. Let’s look at a few examples of how to apply multi-keyword values to the CSS display property.

Switching to a block-level element

If you’re working with an inline element, setting its display property value to block flow can turn it into a block-level element. The children of that element will follow the normal flow layout, behaving as block or inline boxes.

For example, here’s the result of transforming the <span> and <a> elements in our previous example to block-level elements. See this example on CodePen.

This can be useful if you want an inline element to take up the full width of its parent container, display on its own line, or use block-level style properties.

Note that CSS position property values like absolute and fixed also affect the element's display. This happens because these values take an element out of the normal flow, making it function independently.

Switching to an inline element

You can also turn a block-level element into an inline element using multi-keyword values in the display property. The children of that element will then follow the normal flow layout, behaving as block or inline boxes.

Here’s the result of transforming the <li> block elements to inline lists. Check out the CodePen example.

display: block flex; and display: inline flex;

Setting the display property to flex defines an element as flex container. This establishes a new flex formatting context for the element’s contents. The element’s direct children also become flex items and are laid out using the flex layout model rather than following the normal flow.

Note that an element’s outer display type is block by default when a flex value is applied. However, thanks to the CSS Level 3 specification, rather than using a single-keyword value:

element {
  display: flex;
}
Enter fullscreen mode Exit fullscreen mode

We can use two-keyword values for clarity, like so:

element {
  display: block flex;
}
Enter fullscreen mode Exit fullscreen mode

The CodePen below demonstrates how elements in the normal flow behave when you apply block flex to the display property. See the CodePen.

As you can see, we have an inline span container element with span and a children. We also have a block-level article container element with two div children elements. These all behave as expected in the normal flow in their natural state.

If we switch the display from default to flex or block-flex using the select dropdown, the inline container element will become block-level. Meanwhile, the block container element remains unchanged, but its contents change their behavior as they are laid out using the flex layout model.

Suppose you instead wanted to turn the container elements into inline-level elements using the flex layout model. You can do so by applying the inline-flex keyword value — or better yet, applying the updated, more explicit syntax and applying the inline flex multi-keyword value.

See this example on CodePen.

Remember, the single-keyword value inline-flex and the multi-keyword value inline flex will result in the same behavior.

Using both the outer and inner keywords in the display property allows for more clarity.

Switching the display to inline flex turns the block-level container element into an inline-level element. The contents of the container are also laid out using the flex layout model.

With this in mind, we can understand the role of a flex element when building a layout with flexbox.

display: block grid; and display: inline grid;

Setting the display property’s inner value to grid defines an element as a grid container. This establishes a grid formatting context for its contents, ensures that direct children become grid items, and lays out the child elements according to the CSS grid specification.

Like Flexbox, the grid also helps solve certain layout problems. The CodePen below demonstrates how elements in the normal flow behave when you apply the grid keyword to the display property.

See the CodePen.

If we switch the select dropdown from default to grid or block grid, the inline container element becomes block-level, filling the entire parent container, while the block container element remains unchanged. The contents of the containers are also laid out into a grid — you can see how this changes the appearance of the span and a elements.

An element’s outer display type is block by default when you apply a grid value. So, the single-keyword value grid and the multi-keyword value block grid will produce the same result.

But what if you want to define an element as an inline-level element in a grid container instead? You can do so using the inline grid multi-keyword value, which was previously written as the single keyword inline-grid. Check out this updated example:

See the CodePen example.

If we switch the display from default to inline-grid or inline grid, the block-level container element will become an inline-level element. The contents of the containers are also laid out into a grid.

display: block flow-root;

Setting the display property value to flow-root helps contain elements within their parent. flow-root creates a “block-level” element with its own BFC. That means the element will behave like a display: block flow; but with the new root as its formatting context where everything inside is contained.

If you understand the CSS concept of margin collapsing, you’ll know that the vertical margins of adjacent block-level elements collapse into a single margin. A clear example is margin collapsing between sibling elements, like the paragraphs in the CodePen below:

See the CodePen example.

Each paragraph has a 16px margin at the top and bottom. However, due to margin collapsing, the paragraphs don’t have a 32px margin between them. Instead, the resulting margin will be the larger of the individual margins — but in our case, the values are equal, so the margin is just 16px.

While margin collapsing between siblings prevents extra spacing, margins can also collapse between parents and children, which may lead to undesired results.

The CodePen below demonstrates the issue. Try using the dropdown to apply a margin-top to the heading element, creating space within the parent. The margin-top of the child is not contained within the parent but collapses to the outside of it:

See the CodePen.

Even though the margin is not contained within the parent, it’s still contained within the viewport. This is because the root <html> element itself creates a block formatting context.

To contain the margin within the parent element, we can make the parent a new flow root. The multi-keyword syntax explicitly describes the values like this:

element {
  display: block flow-root;
}
Enter fullscreen mode Exit fullscreen mode

In the CodePen below, applying display: block flow-root; ensures that the child’s margin-top is contained within the parent block element. See this example on CodePen.

Applying some other CSS properties on the parent — like padding, border, or overflow — can also ensure margin is contained within its parent.

display: inline flow-root;

Similar to how display: block flow-root; creates a BFC on a block box, we can create a BFC on an inline box. This way, everything inside the inline box will be contained within it. For instance, applying padding, and margin on inline elements can now push other elements away. Similarly, width and height values will also apply.

Previously, we had to use a single-keyword value to achieve this, like so:

display: inline-block; 
Enter fullscreen mode Exit fullscreen mode

Now that we can use multi-keyword values, we can write our display property more explicitly for better clarity:

display: inline flow-root;
Enter fullscreen mode Exit fullscreen mode

Let’s update our original CodePen example to demonstrate this behavior. See the CodePen.

The <span> and <a> are placed inline, as expected of inline elements. However, everything inside the box is now contained. As we can see, we can now apply width, height, margin, and padding properties.

display: block table

Adding the table value to a block-level element’s display property makes it behave like an HTML <table> element. This value used to help with creating complex page layouts. Now, we rarely use it, as we can use the flexbox and grid CSS layout systems, which provide more flexibility.

Consider the following HTML table structure in its simplest form:

<table>
  <tr>
    <td>Id</td>
    <td>Name</td>
  </tr>
  {/* ... */}
</table>
Enter fullscreen mode Exit fullscreen mode

The CodePen below demonstrates how we can replicate the HTML table in CSS with display: block table and other display utilities:

See the CodePen.

In the code, nested elements are displayed as table-row and table-cell.

Reference table: Using multiple CSS display property values

You can use the table below as a reference for how to combine inner and outer display property values to achieve various effects:

Inner display type Outer display type: `block` Outer display type: `inline`
`flow` `display: block flow;` Behaves as a block-level element laid out in a document using the normal flow. Essentially the same as display: block, as block elements default to the standard flow layout. `display: inline flow;` Behaves as an inline element laid out in a document using the normal flow. Essentially the same as display: inline, as inline elements default to the standard flow layout.
`flow-root` `display: block flow-root;` Behaves as a block-level element with a new block formatting context, causing its children to be laid out using the normal flow while preventing margin collapse with other elements. Essentially the same as display: flow-root. `display: inline flow-root;` Behaves as an inline-level element with a new block formatting context, causing its children to be laid out using the normal flow while preventing margin collapse with other elements. Essentially the same as inline-block.
`flex` `display: block flex;` Behaves as a block-level element, but its children are laid out using the flexbox layout. Essentially the same as display: flex, but with explicit outer block-level behavior. `display: inline flex;` Behaves as an inline-level element, but its children are laid out using the flexbox layout. Essentially the same as display: inline-flex, but with explicit outer inline-level behavior.
`grid` `display: block grid;` Behaves as a block-level element, but its children are laid out using the grid layout. Essentially the same as display: grid, but with explicit outer block-level behavior. `display: inline grid;` Behaves as an inline-level element, but its children are laid out using the grid layout. Essentially the same as display: inline-grid, but with explicit outer inline-level behavior.
`table` `display: block table;` Behaves as a block-level table element, making the element behave like an HTML table <table> N/A

Single display values

There are two display values that can only be used by themselves — none and contents. Let’s explore how these keywords work with the display property.

display: none

Using display: none hides an element and its descendants on a webpage. This property is often used to temporarily hide elements that should appear only at specific screen sizes or when triggered by JavaScript.

Be aware that using display: none can cause a potential reflow of the page's layout. If you want to hide an element while keeping the page layout stable, you can use another CSS declaration called visibility: hidden. This declaration makes the element invisible while maintaining its space in the layout.

The CodePen below demonstrates the behavior of the display: none and visibility: hidden declarations. See the CodePen example.

Selecting display: none in the CodePen removes the target span element from the layout. In contrast, visibility: hidden makes the element invisible while retaining its space.

display: contents

Using display: contents makes the element itself disappear, making its children behave as if they are direct children of the parent element. This display value is useful when you don’t have control over the markup, which can affect styling — for instance, when we need to have items in the same container for flex or grid layouts.

In the CodePen example below, the .wrapper element introduces unnecessary nesting, complicating the flex layout. We want the .item elements treated as direct children of the .flex-container so they can be distributed accordingly. So, we apply display: contents to .wrapper to effectively remove it from the layout.

See the CodePen example.

Conclusion

Understanding the CSS display property is important for creating well-organized and attractive websites. This guide explained key display values like block, inline, inline-block, flex, and grid, and how they affect element layout and behavior. It also covered multi-keyword values, which provide clarity by defining both outer and inner display types.

If you found this guide helpful, please share it online. Feel free to ask questions or share your thoughts in the comments section.


Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

LogRocket Signup

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — start monitoring for free.

Top comments (0)