Megan Lee
Posted on June 25, 2024
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;
}
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;
}
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;
}
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;
}
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;
}
However, it’s now recommended to use the multi-keyword value block flow
to be more explicit:
element {
display: block flow;
}
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;
}
We can use two-keyword values for clarity, like so:
element {
display: block flex;
}
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.
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:
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;
}
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;
Now that we can use multi-keyword values, we can write our display
property more explicitly for better clarity:
display: inline flow-root;
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>
The CodePen below demonstrates how we can replicate the HTML table in CSS with display: block table
and other display
utilities:
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 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.
Posted on June 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024