Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between visibility: hidden and visibility: collapse in flexbox?

In the CSS flexible box layout module, it says:

the collapsed flex item is removed from rendering entirely, but leaves behind a "strut"

Does that behave just like visibility: hidden? If the answer is yes, then why was visibility: collapse introduced?

like image 359
everywill Avatar asked Feb 15 '17 14:02

everywill


People also ask

What is the difference between hidden and collapsed?

Hidden hides the control, but reserves the space it occupies in the layout. So it renders whitespace instead of the control. Visibilty. Collapsed does not render the control and does not reserve the whitespace.

What is the difference between a collapsed element and a hidden element?

Hidden: Do not display the element, but reserve space for the element in layout. Collapsed: Do not display the element, and do not reserve space for it in layout.

What is the difference between visibility hidden and display?

visibility:hidden will keep the element in the page and occupies that space but does not show to the user. display:none will not be available in the page and does not occupy any space.

What is visibility collapse?

visibility: collapse hides an element entirely (so that it doesn't occupy any space in the layout), but only when the element is a table element. If used on elements other than table elements, visibility: collapse will act like visibility: hidden .


1 Answers

Note on browser support: As of July 2017, Chrome (59) does not support visibility: collapse. The code samples below with collapse work in Firefox and Edge, but fail in Chrome (they behave just like hidden). UPDATE: As of July 2020, this is note is still valid. Chrome and Safari treat visibility: collapse like hidden. caniuse.com


Flex items are laid out in a row or column, depending on flex-direction.

Each row / column is considered a flex line.

In the examples below, a flex container has four flex items in row-direction. The fourth item wraps, creating a second flex line:

.container {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  border: 1px dashed black;
}
.box {
  height: 50px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: lightgreen;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
</div>

display: none

With display: none, a flex item isn't rendered by the browser.

If all items on the flex line have display: none, the line also collapses, which affects the rest of the layout. Surrounding elements may shift when a flex line collapses.

With display: none applied to the third item, the fourth item takes its place on the upper line, and the lower line collapses:

.container {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  border: 1px dashed black;
}
.box {
  height: 50px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: lightgreen;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box3 { display: none; }
<code>display: none</code>
<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
</div>

visibility: hidden

With visibility: hidden, a flex item is rendered by the browser but is fully transparent. It's hidden from view but takes up the space it would normally use in the layout. Hence, surrounding elements see this item as fully intact.

In this example, when the last two boxes have visibility: hidden, the rest of the layout (including the second flex line) remains unchanged.

.container {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  border: 1px dashed black;
}
.box {
  height: 50px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: lightgreen;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box3 { visibility: hidden; }
.box4 { visibility: hidden; }
<code>visibility: hidden</code>
<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
</div>

visibility: collapse

With visibility: collapse, a flex item is not rendered (same as display: none), but the flex algorithm checks the cross size of the item and then uses that data to keep the flex line stable (i.e., what the cross size of the line would be if the flex item was visible).

The difference with display: none is that collapse allows one piece of the item – its cross size – to be preserved. This is referred to in the spec as the strut.

So if all flex items on the line have visibility: collapse, the cross size of the line (whether it be the width or height) does not collapse, and the rest of the layout isn't affected.

Note that although collapse guarantees the stability of the line's cross size, it provides no such assurance for the line's main size. This is a key difference between collapse and hidden.

Below are some examples. (As mentioned above, these won't work in Chrome. Test in FF or Edge.)

In this example, the first two items have visibility: collapse.

.container {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  border: 1px dashed black;
}
.box {
  height: 50px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: lightgreen;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box1, .box2 {
  visibility: collapse;
}
<code>visibility: collapse</code>
<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
</div>

The layout renders like display: none. The second line collapses because the main size of the items is gone, allowing the last item to move up naturally.

In the following example, all items get visibility: collapse. Hence, the second line collapses because the items' main size is gone, but the cross size of the first line remains.

.container {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  border: 1px dashed black;
}
.box {
  height: 50px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: lightgreen;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box {
  visibility: collapse;
}
<code>visibility: collapse</code>
<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
</div>

jsFiddle

like image 93
Michael Benjamin Avatar answered Sep 20 '22 04:09

Michael Benjamin