How well do you know CSS display?
chenhuijing.com
chenhuijing.com
When I'm fixing cross-browser bugs nowadays it's mostly about flexbox. It's not very often and I can always fix it in a small amount of time. But it gives me an unpleasant but also nostalgic flashback of the old days in the 00s where I fixed more CSS than I originally developed.
So yes, from time to time I run into different and not so obvious problems. My holy grail to work with flexbox today is this list:
https://github.com/philipwalton/flexbugs
Two recent issues I ran into: There is a very nasty "bug" in the current Firefox browser. It's not a real bug- more a different interpretation of the standard which will hit any developer not working primarily with Firefox I guess. It's about the intrinsic size of a flex item in combination with fluid images. You have to apply min-width: 0 to the flex-item or you get a (very) wrong sizing in some circumstances. See [2] and [3]
And another one. Most of the time I think about IE11 that it's a mostly 'modern' browser and therefore supports flexbox very good. Yes it is good enough to use. But don't underrate the flexbox bugs (just glimpse through [1]). For example you have to set `min-height > 1px` on a flex container to prevent it from collapsing in some scenario (holy grail layout is a very common case). See here [4]
[1] https://github.com/philipwalton/flexbugs
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1108514
----
https://drafts.csswg.org/css-display/#propdef-display:
> The `display` property defines box’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 box participates in its parent formatting context.
...
> <display-outside> = block | inline | ...
> <display-inside> = flow | flow-root | table | flex ...
...
Short `display` | Full `display` | Generated box
----------------|--------------------|---------------
'block' | 'block flow' | block-level block container
'flow-root' | 'block flow-root' | block-level block container that establishes a new block formatting context
'inline' | 'inline flow' | inline box
'inline-block' | 'inline flow-root' | inline-level block container
----------------|--------------------|---------------
'flex' | 'block flex' | block-level flex container
'inline-flex' | 'inline flex' | inline-level flex container
--------The advent of this kind of explicit systematic consistency in web standards is pretty much my favourite thing about living in the future. Every day I fall to my knees and cry with joy and gratefulness that I will only have spent this a small fraction of my professional engagement with web things in the abominable hellscape that was this world before CSS3 started being widely implemented.
https://www.w3.org/TR/2014/WD-css-display-3-20140911/#the-di...
---
But that has since been changed to `display` being a "one property that takes multiple values" shorthand, in the current version of the spec:
https://www.w3.org/TR/2015/WD-css-display-3-20150721/#change...
> Changes since the 11 September 2014 Working Draft include:
> Removed `display-inside`, `display-outside`, and `display-extras` longhands, in favor of just making `display` multi-value. (This was done to impose constraints on what can be combined. Future levels of this specification may relax some or all of those restrictions if they become unnecessary or unwanted.)
--------
But you're right. It's not even on caniuse yet (vote here: https://github.com/Fyrd/caniuse/issues/2337).
But I'm stoked to even see these orthogonal axes and their domains officially laid out, and names given to concepts. Even just `display-inside` vs `display-outside`.
I've had discussions with professionals where no one was certain enough about the `display` mess to make any confident statements on the exact nature of the similarity between `flex` and `block`. Who knew if there were edge cases that made them not have (what I now have the words to describe as) the same `display-outside` behaviour? Thanks also to the crazy muddle of just-slightly-different behaviour the proliferation of other display options has scarred us all with, previously all sharing a single, very arbitrary-seeming, axis.
Until then, I'll stick with flexbox. Someone has already made this excellent set teaching tool: http://flexboxfroggy.com/
Granted, I've never sat down and systematically learned the foundations of CSS, but I also never did that with Python, Javascript, Clojure, Bash, PostgreSQL, etc. and yet with all of those, I've not had nearly the number of infuriating, soul-crushing marathon sessions of Googling, Stack Overflowing, grasping randomly in the dark, and making desperate prayers to the binary gods.
[0] https://github.com/facebook/css-layout#default-values
[1] https://github.com/necolas/react-native-web/blob/master/docs...
@media screen and (min-width: 720px) {
.th {
font-size: 1.294rem;
line-height: 1.6rem;
}
}
@media screen and (min-width: 720px) {
.th {
font-size: 0.8rem;
line-height: 1.6rem;
font-family: "Roboto Slab", Rockwell, serif;
font-weight: 700;
}
}
@media screen and (min-width: 720px) and (min-width: 720px) {
.th {
font-size: 1rem;
line-height: 1.6rem;
}
}It causes issues such as:
- The built-in rule for *[hidden] { display: none; } is often of no help as another css class may set display to something else, so from the developer's perspective the "hidden" attribute seems to be broken.
- Often a CSS class sets display:none and another CSS class which merely wants to undo that sets display:block. This gets in the way of the developer if they really wanted to use another display type like flex. (one example: Bootstrap's tabs, .tab-content.active{display:block})
- In both cases the fix gets ugly in cases where the problematic css which you want to override comes from parent classes elements, as in that case it is not sufficient to use a simple class like .display-flex{display:flex;} but you need complex rules to override specific cases of parent css.
This is exactly what the proposed box-suppress property [1] does:
"The display: none value was historically used as a "toggle" to switch between showing and hiding an element. Making this reversible requires either setting up the CSS cascade carefully, or remembering what the display value was before it was set to none. To make this common use-case easier, this module introduces the separate box-suppress property to do the same thing, so that toggling whether or not an element appears in the formatting tree can now be done without affecting its display type when it is displayed."
[1]: https://drafts.csswg.org/css-display/#propdef-box-suppress
Best case is that you don't have one class that applies block (or whatever) and another that applies none. You let the element display as its default state and then you have a class that hides it, possibly overriding the CSS of the element. You then remove/add the class as needed. The .show() and .hide() in jQuery caused problems like you described for years.
As for your third example, I would say the CSS structure should be considerd broken at that point and should be refactored because something went wrong along the way.
[hidden] { display: none !imporant; } is one of the few examples where I think `!important` is OK.
I have a rule that if I'm Googling a symptom for the second time that I have to take some time to learn more about the subject.
The fact that a lot of other people here are saying that they have to fiddle with CSS to get it right is making me feel a lot less shitty as a web dev.
Better yet, he could have set `white-space: nowrap;` on `.passenger__label` instead and just thrown a `<wbr>` element before the first parenthesis.
probably the biggest problem with it.
It was hard enough to get permission to drop IE <10 at $EMPLOYER.
If you're trying to implement something with layout constraints in both dimensions, you want grid. If you're not, you can probably use grid, but flexbox is likely easier.
With flexbox you get layout constraints in both dimensions with proper source nesting (rows inside columns or vice versa, ad infinitum) and you get source order independence in the "current direction" (within this row or this column), but not between rows/columns in the grandparent container (or the great-grandparent, etc).
With grid, you can have source order independence in both directions, very nice and easy.
(Source order independence matters for responsive needs where things reflow to different grid places/flex orders based on viewport width, media type or other factors. Source order independence can also be a big important factor for accessibility. The "semantic web dream" is kind of sort of dead or at least asleep these days, but source order independence is a huge win for the semantic web. Finally, source order independence is just nice for keeping HTML markup clean and minimal, which has long been the dream of CSS.)