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 mainlyblcok
,inline
andrun-in
<display-inside>
: Its values mainly includeflow
,flow-root
,table
,flex
,grid
andruby
<display-listitem>
: Its values mainly include< display-outside >
,flow
,flow-root
andlist-item
<display-internal>
: Its values are mainlytable-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
andruby-text-container
<display-box>
: Its values mainly includecontents
andnone
<display-legacy>
: Its values mainly includeinline-block
,inline-table
,inline-flex
andinline-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, readdisplay: 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:
- Left and Right in the Web: LTR vs. RTL in Flexbox and Grid Layouts
- Left-to-right in Web: Common errors in switching from LTR to RTL in Web layout
- CSS logical properties and logical values
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? ".