Do you really understand CSS display?

w3cplus
14 min readFeb 3, 2024

After learning the CSS box model and visual formatting model , we have a clear concept. That is, any element inserted in CSS is a box, even text nodes are also boxes (anonymous boxes); they all have their own visual formatting (different boxes) . Among them, the CSS display property can explicitly modify the visual formatting model of each box, such as changing from inline-level boxes to block-level boxes . In this chapter, we will explore the CSS display property together, which is also one of the indispensable properties for learning CSS.

Display basic introduction

The display property of CSS is an independent module in the W3C specification, namely CSS Display Module Level 3 . This module describes how to generate a CSS tree (CSSOM tree) from a document tree (DOM tree) and defines how to use the display property to control CSSOM. For example, let's take an HTML document like the following:

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="style.css" rel="stylesheet">
<title>Critical Path</title>
</head>
<body>
<p>Hello <span>web performance</span> students!</p>
<div><img src="awesome-photo.jpg"></div>
</body>
</html>

The document structure is very simple, containing only some text and an image. If you understand the rendering principle, you can understand that the browser processes the HTML page like this:

Ignore the rest, focus on the DOM build part here.

Since HTML tags define the relationship between different tags (tags refer to HTML element tags) (some tags are included in other tags), the created objects are linked in a tree data structure, which also captures the parent-child relationship defined in the original tag, such as < html > object is the parent element of < body > object, < body > is the parent element of < p > object, and so on:

The final output of the entire process is the Document Object Model (DOM) of our simple page, which will be used by the browser for all further processing of the page.

In this example, we use the < link > tag to import a style.css style file with the following style code assumptions:

body {
font-size: 16px
}
p {
font-weight: bold
}
span {
color: red
}
p span {
display: none
}
img {
float: right
}

Just like when dealing with HTML, we need to convert the received CSS rules into something that the browser can understand and process. Therefore, we will repeat the HTML process, but for CSS instead of HTML.

CSS bytes are converted into characters, then into tokens and nodes, and finally linked into a tree structure called the “CSS Object Model” (CSSOM).

The browser will merge the DOM tree and CSSOM tree into a Render Tree.

With the rendering tree, we can enter the “layout” stage.

In CSS, for each element, CSS generates zero or more boxes (boxes) based on the element’s display property. Typically, an element generates a separate box (box), which represents the element itself and contains its content in the box tree. However, some display values (such as display: list-item ) will generate multiple boxes (one body box and one Marker box); some values (such as display: none or display: contents ) will lead to the element or its descendants not generating any boxes. Simply put, the element's box type is determined by the value of the display property. For example, the most familiar display: block will make the element generate a block-level box, display: inline will make the element generate an inline-level box.

For an introduction to frames (or boxes), read the chapter on visual formatting models .

To put it in one sentence, the CSS display property can be used to change the visual formatting model of an element, that is, to change the type of the box .

Basic properties of display

The display property defines the display type (visual formatting model) of an element. By default, browsers set a display value for elements, such as the < p > element in the example above:

In CSS, we can explicitly set the value of display to change the box model of the element. The common properties of CSS display are mainly divided into:

  • <display-outside> : Its values are mainly blcok , inline and run-in
  • <display-inside> : Its values mainly include flow , flow-root , table , flex , grid and ruby
  • <display-listitem> : Its values mainly include < display-outside > , flow , flow-root and list-item
  • <display-internal> : Its values are mainly table-row-group , table-header-group , table-footer-group , table-row , table-cell , table-column-group , table-column , table-caption , rub-base , ruby-text , ruby-base-container and ruby-text-container
  • <display-box> : Its values mainly include contents and none
  • <display-legacy> : Its values mainly include inline-block , inline-table , inline-flex and inline-grid

In layout, the most common display attribute values are block , inline , inline-block , table and none . There are also several new layout favorites, namely flex , inline-flex , grid and inline-grid .

display: inline

This element generates one or more inline boxes. The space occupied by inline-level elements is the size defined by their tags (determined by the element content).

display: block

This element generates a block-level box. Unless otherwise specified, all block-level elements start on a new line and extend to the width of their container.

display: inline-block

This element generates a block-level box, but the entire box behaves like an internal connection-level element.

The differences between inline , block and inline-block are depicted in the following figure:

display:list-item

The element is rendered as a list item, exactly like a block-level element, but generates a markup box (i.e. Marker markup box) that can be styled by the list-style attribute. Among many HTML elements, only the li element can have a default value of list-style .

For non- li elements, you can explicitly set display: list-item to generate. Using list-item will produce two box modes, one is a block box and the other is a Marker marker box:

Regarding the Marker tag, there is an independent ::marker pseudo-element in CSS that can be used. For more detailed information, please read the ::marker section in the article "CSS Counter: @counter-style ".

Table-based layout

There is a <display-internal> in the value of the display attribute, which mainly allows us to use display -related values to make the behavior of the element similar to HTML's <table> .

Although most of us no longer use table-based layouts, <display-internal> in display is still useful in certain situations. <display-internal> The specific values are shown in the table below:

display: none

Remove the element and its child elements from the normal document stream. At this time, the rendering of the document is as if the element never existed, that is, the space it occupies is collapsed. The content of the element will also be ignored by the screen reader.

And explicitly setting display: none will not produce any boxes, and its descendant elements will not produce any boxes.

display: flex / inline-flex

When an element declares display as flex or inline-flex , the element generates a flex container and its child elements become flex projects.

For more information about Flexbox layouts, read the Flexbox related chapters in Modern Web Layouts .

display: grid / inline-grid

When an element declares display as flex or inline-grid , the element generates a Grid container and its child elements become Grid projects.

For more information on Grid layouts, read the Grid related chapters in Modern Web Layouts .

display: contents

display with a value of contents can remove an element from the Box Tree, but the content will remain:

The element itself does not generate any bounding boxes, but the child elements and pseudo-elements of the element still generate bounding boxes, and the element text is displayed as usual. In order to take care of the bounding box and layout at the same time, when processing this element, it is necessary to imagine that this element is not in the element tree structure, but only the content is left. This includes the child elements and pseudo-elements of the element in the meta-document, such as ::before and ::after these two pseudo-elements, as usual, the former is still generated before the child elements of the element, and the latter is generated after.

The display: contents style rule makes the div element not produce any bounding boxes, so the background, borders, and padding of the element are not rendered. However, inherited properties such as color and font still affect the span child element.

For more information on the display: contents layout, read display: contents changes Flexbox and Grid layout modes in Modern Web Layouts .

display:flow-root

Use display: flow-root to explicitly create a BFC. This value creates the BFC on the block, not the internal connection element.

Display changes to the document flow

When the browser parses any document, by default, it will render the document stream as shown in the figure below.

If we use CSS display , we can make changes to any document stream, as shown in the following figure:

Colleagues with some CSS foundation know that using display can change the visual formatting model of elements and have certain changes to the document flow. Moreover, what is more familiar is only the use of some commonly used attribute values, but there are still significant changes in CSS display . Next, let's take a look at the changes brought to the document flow.

As mentioned earlier, the display property defines the display type of an element, which consists of two basic properties of the element spawning box:

  • The inner display type , which defines (if it is a non-replaceable element) the type of formatting context it generates, specifying how its descendant boxes are laid out
  • External display type , which indicates how the body box itself participates in the flow layout

The block and inline elements (or elements with display set to these two values) are easy to understand, but what happens if the element explicitly sets display: grid ?

The display: grid is explicitly set for an element in the layout, and its behavior is similar to that of a block-level element ( display: block ). The element will expand and occupy as much space as possible in the inline dimension, starting from a new line. Its behavior is like a block element, working together with other parts of the layout.

In fact, in the display specification (Level 3), the value of this attribute is defined as two keywords . These keywords define the external value of the display , which will be inline or block , thus defining the behavior of the element with other elements in the layout. They also define the internal values of the element (the behavior of the immediate child elements of the element).

This means that when you use display: grid , you are actually using displah: block grid . This means that the layout requires a block-level grid container. That is to say, the element has the properties of a block element, that is, you can set width , height , padding and margin to the element, and the element itself will automatically stretch to fill the container. At the same time, the child elements of this element have been given internal values of grid , so the child elements become what everyone calls grid items .

This way of thinking can better help us explain various layout methods in the Web. For example, if you set display: inline flex , it means that you need an internal connection element box, and its child elements are Flex projects.

Using a picture to describe, it is easier to understand:

A more detailed introduction can be found in the block axis and internal connection axis section of the CSS box model .

Note that in the layout, the internal connection axis and block coupling have a close relationship with the writing mode, as shown in the following figure:

Therefore, it will also directly affect the layout effect.

If you are interested in this part, I suggest you read the following articles:

So far, people are used to setting a value explicitly for the display , and in the near future, it may be more habitual to set two values. Especially in the layout, setting two values explicitly makes it easier for everyone to understand the layout:

With the above table, it is clear to use double values in display . Even if we go back to the world of single values, it can help us understand. For example, display: block is equivalent to display: block flow-root , defining a BFC block-level box.

Simply put, when laying out in CSS, the behavior of this box is defined based on its relationship with all other boxes in the layout, and the behavior of the child elements of this box is also defined.

Display brings changes to visual formatting models

As mentioned in the introduction of the box model and the visual formatting model, anything in CSS will generate a box. Each value of display will change the formatting model of the element. For example, if you explicitly set the value of display to inline for a block-level element div , the element will be rendered visually as an inline-level box; similarly, if you explicitly set the value of display for a span element to block , the element will be rendered visually as a block-level box.

We spent a lot of space introducing the value of the display property, but there are two values in display , none and contents , which have different ways of formatting boxes. For example, if an element has some child elements, you want it to not generate any boxes in the layout (especially in Flexbox and Grid layouts), as shown in the following figure:

In fact, none and contents in CSS display can help us respectively:

  • Use display: none to prevent the element itself and all its descendants from generating boxes
  • Using display: contents prevents the element itself from generating boxes, but its descendant elements will still generate boxes

That is to say, when you do not want an element or even its descendants to appear in the layout, you can explicitly set display: none in the element. At this time, the element box will be removed from the Box Tree and behave as if the element does not exist at all. Therefore, this setting is very useful if you want to hide the element.

Using display: none will hide the element from all users, including screen readers. This is not very friendly for website accessibility, especially for users with disabilities. However, in CSS, there are many technical solutions to simply hide an element, and it is not recommended to use display: none to hide the element unless absolutely necessary.

Using display: none can hide both elements and their descendants. However, sometimes there are slightly different scenarios. For example, if you want to remove the element itself from the box tree, but its descendants do not want to be removed from the box tree, you can use display: contents . Let's take an example:

<!-- HTML -->
<div class="box">
<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<ul>
<li>li 1</li>
<li>li 2</li>
<li>li 3</li>
</ul>
<div>div 4</div>
</div>
<div class="box contents">
<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<ul>
<li>li 1</li>
<li>li 2</li>
<li>li 3</li>
</ul>
<div>div 4</div>
</div>
.box {
display: flex;
div {
min-width: 100px;
min-height: 100px;
background: #f36;
}
li {
min-width: 100px;
min-height: 100px;
background: orange;
}
}
.contents ul {
display: contents;
}

The effect you will see is as follows:

From the above figure, we can see that the ul element without explicitly setting display: contents will treat the entire element as a Flex project, while the li element is still a list-item , not a Flex project; while the ul with display: contents set, ul itself will be removed from the box tree, and li will become a Flex project. That is to say, in some scenarios, when you only want to remove the element itself from the box tree, but also want to affect the descendant elements of the element, explicitly setting display: contents on the element is very useful.

There are advantages and disadvantages. If display: contents is explicitly used on an element, the margin and padding on the element will be removed. This is because display: contents removes the element from the box tree, so the properties related to the box have nothing to do with the element. This may also lead to another assumption that using display: contents is a good way to quickly remove padding and margin on elements.

Another shortcoming is that setting up the element of display: contents will also have a certain impact on the accessibility of the Web page. However, the discussion about accessibility is beyond the scope of this article. If there is a chance, I will find another opportunity to discuss it with you.

Summary

In this chapter, we mainly briefly learned about the property values of display in CSS and its meaning in web layout. Explicitly setting the value of display on the element can easily reset the visual formatting model of the element, and also create different formatting contexts, such as BFC, IFC that everyone is familiar with, as well as FFC, GFC, and TFC that everyone is not familiar with. In addition, the new property or usage of display in CSS will bring more changes to the layout and help everyone understand the layout more easily. Especially when using two keywords in the display property, you can clearly understand the role of the element in the layout.

Here is just a simple introduction to the CSS display property, which can be regarded as popular science. Because each value of display is involved in other specifications, for example, in the Flexbox layout, it is introduced that using display: flex or inline-flex will generate a Flex container, and its sub-projects will generate a Flex project. Then, when introducing different layouts in detail later, we will continue to talk about the knowledge related to display .

If you want to further understand the impact of the display property on the CSS visual formatting box model, you can read the article " Defensive CSS Insights " in " How to Choose a Visual Box Model Based on UI Form? ".

--

--

w3cplus

Author of "Modern CSS," "Modern Web Layout," "In-Depth CSS Defense," and "A Journey into Web Animation!"