Ekaterina Vujasinović
Posted on February 10, 2020
If you are just like me and have spent a last couple of years coding without being aware of how many CSS display values are out there, this could be a useful post for you. I will leave out the values that are most widely used (block
, inline
, inline-block
, flex
, grid
, table
with all the internal display values and none
) since there are already so many great articles about them.
Table Of Contents
👉 What display is all about
👉 display: inline-flex and display: inline-grid
👉 display: flow-root
👉 display: list-item
👉 display: contents
👉 display: ruby
What display is all about
According to the CSS Display Module Level 3 spec 👇
The display property defines an element’s display type, which consists of the two basic qualities of how an element generates boxes:
👉 the inner display type, which defines the kind of formatting context it generates, dictating how its descendant boxes are laid out.
👉 the outer display type, which dictates how the principal box itself participates in flow layout.
In other words, the inner display type describes the behaviour of element's children, while the outer display type defines whether the element is block-level or inline-level, that is, how it interacts with other, outer elements.
Right now, display property single-value syntax feels kind of incomplete and doesn't always let you specify both inner and outer display type explicitly. Sometimes it's hard to figure out right away how the element behaves.
Luckily, the CSS Display Module Level 3 also defines new, two-value syntax for setting display values, with outer and inner display type values set separately (e.g. block flex
instead of just flex
). This feature has already been implemented in Firefox, but other browsers don't support it yet.
display: inline-flex and display: inline-grid
Both flex and grid containers are behaving like block items by default, as both flex
and grid
display values are setting the outer display type to block. This means that each container will occupy the full width available, even if its corresponding HTML element is an inline item (like <span>).
In case we need to modify the outer behaviour of the grid / flex containers, e.g. to position them side-by-side in the same row, 👉inline-flex
and inline-grid
display values will make them behave like inline elements, without affecting the layout of items inside the containers.
display: flow-root
flow-root
is an inner display type value, which means that it sets the inner flow of the elements. In order to properly understand flow-root
, we need to dig into something called Block Formatting Context (BFC). There is a definition in the spec, but it's easier to explain with an example.
There are two red <div> elements in CodePen below, with identical children elements and formatted in the same way, except for the display value. The first container has default, block
display value, while the second one is an inline-block
element. Do you see collapsed margins in the first container? 😱
Top margin of the blue square and bottom margin of the paragraph are somehow ending up outside of the parent element. In the second container, we avoided margins collapsing, since it occurs only between blocks belonging to the same Block Formatting Context and 👉 display value of inline-block
creates a brand new BFC.
inline-block
is not the only property creating a new BFC, though. What if we want to keep the margins from collapsing, but also keep our container block element, remaining in his own row in layout? Among other hacks, we could do it by setting overflow to hidden, but apparently, this method may have unwanted side effects.
👉 flow-root
display value is a solution to our problem as it always generates a block container box and establishes a new BFC for its content. As an inner display type, it is actually short for block flow-root
, whereas inline flow-root
is identical to inline-block
value.
Now we can use display values to create new BFC on both block and inline elements, which can be useful not only when handling margins, but for example, when we need to contain floats without using the clearfix hack.
Rememeber, the two-value syntax is not quite alive yet, so you can't use display: inline flow-root
(except in Firefox). 👉 Use display: flow-root
(but check the browser support first) and display:inline-block
instead.
display: list-item
list-item
is the default display value for <li> element. It generates a block box for the content and a separate inline box for the marker. In Firefox, the <summary> element also has list-item
default display value, but only if it is the first child of the <details> element.
You can specify image, position and type for the list marker, but not distinct styles (like colors or fonts). However, in Firefox list-item
creates a ::marker
pseudoelement, which has a wider set of allowable properties.
Yes, I use this one quite a lot, but most of the time I wasn't aware that list items use this special display value. Why does it even matter? Well, in the two-value syntax list-item
can be combined with both outer and inner display types, making really long display values (like inline flow-root list-item
).😄
display: contents
Display values of contents
and none
define whether an element generates display boxes at all.
While element with display:none
will be removed from the layout together with its descendants, 👉 display value of contents
removes only the element from the document tree and its children are replacing it. Use it with care as it is marked as an experimental feature on MDN 🧪, although with fairly good browser support.
It makes it especially beneficial to use with Grid or Flexbox, since only the direct descendants of grid or flex containers are behaving as flex /grid items. In case we need to go down one level and make 'the grandchildren' behave as flex / grid items of the main container, 👉 display:content
on the direct child of the main container will prevent it from generating a box, and its children will take its place.
In the example below, both purple rectangles are grid containers with orange rectangles as children and grid items. Yellow rectangles are children of the first orange rectangle. In the second container,👉 first orange rectangle is given display value of contents
and is no longer visible. His children (yellow rectangles) are taking his place as grid-items, acting as if they were direct descendants of purple rectangle.😎
display: ruby
Ruby annotations are used for adding explanation or pronunciation to base text (usually to East Asian characters). There are two ways of adding a ruby annotation:
👉 with HTML <ruby> element (and corresponding <rt>, <rb>, <rtc> and <rbc> elements for the internal structure)
👉 with CSS display value of ruby
(and corresponding ruby-text
, ruby-base
,ruby-text-container
and ruby-base-container
display values for the internal structure)
When to use CSS display: ruby
?
For document languages (such as XML) that **do not have pre-defined ruby elements **like HTML does, corresponding elements can be translated to ruby elements with the CSS display: ruby
property.
When to use HTML <ruby>?
In all other cases. If you have <ruby> element available, you should use it.
Authors using a language (such as HTML) that supports dedicated ruby markup 👉 should use that markup rather than styling arbitrary elements (like <span>) with ruby display values. Using the correct markup ensures that screen readers and non-CSS renderers can interpret the ruby structures.
—W3C, CSS Ruby Layout Module Level 1
That is, the two aren’t mutually exclusive, but I probably won't use CSS display: ruby
very often. I tried them both in Firefox and found some subtle differences in default behaviour, which indicates there is still room to further investigate this matter.🤯
It seems like HTML <ruby> alone is good enough for a simple ruby structure, along with some optional ruby-related CSS properties to fine tune the positioning of the ruby text.
Posted on February 10, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024