Flexbox seems to be ignoring CSS specificity
Asked Answered
C

1

3

I am attempting to use Flex-By-Default in the same manner as Facebook's CSS layout project. I am having some trouble when it comes to overriding the styles for display: inline-flex elements. Per this jsfiddle:

enter image description here

The HTML, with two '.test-me' divs:

<body>
  <h1>TEST</h1>
  <div class="test-me">
        I'm correctly displayed as inline-flex
  </div>
  <div>
    <div class="test-me">
         'Styles' shows inline-flex, but 'Computed' shows flex
    </div>
  </div>
</body>

Here is the styling:

.test-me {
  display: inline-flex;
  background-color: green;
  border: 1px solid black;
  margin: 6px;
}
div, span {
  display: flex;
  /* Commenting out flex-direction makes second test-me div display correctly */
  flex-direction: column; 
  background-color: purple;
}

I am am slightly concerned this is a browser bug: in Chrome Developer Tools, 'Styles' shows 'inline-flex' winning (as it's from the more specific styling), but 'Computed' shows 'flex'.

Even though 'display: flex' is crossed out (since it's overridden by 'display: inline-block'), disabling the already crossed-out style fixes the issue.

Cecil answered 16/11, 2015 at 16:3 Comment(2)
Computed is showing inline-flex just fine for me on the jsfiddle. Using Chrome Canary, so seems like a bug in your version of Chrome. Next update (maybe two) should fix it.Cutwater
@garbee: Computed shows 'display: flex' the latest Chrome Canary, 49.0.2567.0. Screenshot: imgur.com/EAbJJuTCecil
I
1

Revised Answer

@BoltClock, in the comments, provides the relevant section in the spec covering this behavior.

Section 4. Flex Items

The display value of a flex item is blockified: if the specified display of an in-flow child of an element generating a flex container is an inline-level value, it computes to its block-level equivalent.

This means that in a scenario like the one described in the question, where a child of a flex container is given an inline-level value, the child computes to its block-level equivalent. In a nutshell, the flex item with display: inline-flex becomes display: flex.


Original Answer

I am am slightly concerned this is a browser bug: in Chrome Developer Tools, 'Styles' shows 'inline-flex' winning (as it's from the more specific styling), but 'Computed' shows 'flex'.

Tested your code in Chrome, Firefox and Internet Explorer 11. The behavior is all the same. So I wouldn't say this is a browser bug.

Although you are correct that in Chrome (and Firefox) the inspector shows 'Styles' having inline-flex and 'Computed' having flex, in IE11 it shows inline-flex on both panes, but it renders like the others nonetheless.

A reading of the spec suggests that flex items can only be block elements. Even though you're applying display: inline-flex to the div, the same div is a flex item of a larger container with display: flex. The flex item with inline-flex is possibly being overridden as part of the flex formatting context.

Although there is no direct reference to the spec, here's another answer that may be helpful: https://mcmap.net/q/694101/-block-elements-only-inside-flex-item

Imaret answered 16/11, 2015 at 17:32 Comment(8)
"A reading of the spec suggests that flex items can only be block elements." Isn't the purpose of inline-flex to display the element inline, and have it's contents laid out via flex?Cecil
Yes, inline-flex should do an inline displayed flex container per the specification.Cutwater
@mikemaccana, yes, I believe your statement is correct. But what if display: inline-flex is applied to a flex item of a larger container with display: flex applied? That's the issue I raised in my answer. Your question highlights the possibility (since I couldn't find any concrete data) that a conflict exists, and that display: flex wins, regardless of specificity. Plus, since there doesn't seem to be anything explicit about this in the spec, browsers may have different implementations.Imaret
"the possibility (since I couldn't find any concrete data) that a conflict exists, and that display: flex wins, regardless of specificity" Thanks for helping, but this would really be better as a comment rather than an answer, given the aforementioned lack of data.Cecil
By "lack of data" I only meant lack of explicit guidance in the spec. That was the context and scope of use for the word. I probably shouldn't have used "data" since there is plenty of data suggesting my answer is correct in your example, Chrome dev tools, and FF and IE11 inspectors. The W3C specs don't cover everything; they leave many things open to browser interpretation.Imaret
@Michael_B: From section 4, "The display value of a flex item is blockified: if the specified display of an in-flow child of an element generating a flex container is an inline-level value, it computes to its block-level equivalent." which means the display: inline-flex flex item becomes display: flex.Nitriding
@mikemaccana, answer revised.Imaret
@mikemaccana, is the revised answer more clear? lmk if you have any questions.Imaret

© 2022 - 2024 — McMap. All rights reserved.