How to Style Anonymous Flex Items Explicitly

Is it possible to style anonymous flex items explicitly?

No. Anonymous boxes cannot be directly targeted for CSS styling. CSS styles need a "hook" in the HTML to attach to. That hook is an HTML tag. Without the tag, CSS has nothing to target. This concept applies across box models, including flex and block formatting contexts.


More about anonymous boxes:

From the CSS spec:

9.2.2.1 Anonymous inline
boxes

Any text that is directly contained inside a block container element
must be treated as an anonymous inline element.

The flexbox specification provides for similar behavior.

4. Flex Items

Each in-flow child of a flex container becomes a flex item, and each
contiguous run of text that is directly contained inside a flex
container is wrapped in an anonymous flex item.

Does the CSS flexbox module work on direct child elements only?

To answer your question title: yes, this is actually stated quite clearly in the spec:

The contents of a flex container consists of zero or more flex items: each child of a flex container becomes a flex item

In case the wording in the spec confuses you, that's because your wording is a bit off:

They are childs but not direct childs.

A child is direct by definition... the inner divs are called descendants, but not children in that they're not directly nested within the flex container.

Now, anything with display: flex or display: inline-flex is designated a flex container. While each flex item participates in the flex container's formatting context, the flex item's descendants are formatted independently and regardless of the flex container, being the same as if the container was never flexed in the first place.

As such, you can't reorder descendants of flex items, except if the flex item itself is also made a flex container for its descendants, but even then you cannot reorder them beyond this inner container and around the container's siblings with respect to the outer container.

Flexbox: Align between bottom and center?

You can try this layout:

  • Anonymous element with flex: 1
  • The title and subtitle (titles)
  • Element with flex: 1 and display: flex.

The elements above and below the title will take available space left by titles in equal amounts. So the titles will become centered.

Those elements can also be flex containers, and you can align their contents inside them as desired.

html, body {height: 100% } * { margin: 0; }

.aligner, .below {

display: flex;

justify-content: center;

flex-direction: column;

align-items: center;

}

.aligner {

height: 100%;

}

.aligner::before { content: ''; }

.aligner::before, .below {

flex: 1;

}
<div class="aligner">

<h3>SUPERMAN</h3>

<p>FTW</p>

<div class="below">

<button>BUTTON</button>

</div>

</div>

How display flex affects on line-height of element?

It works as expected with text, and always applies line-height for text.

And you no more have text in your case when you apply inline-flex and flex. You deal with flex-level element and no more inline-level elements

A flex item establishes an independent formatting context for its contents. However, flex items themselves are flex-level boxes ref

and

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 equivalen

So your example

<div style="display:flex; line-height: 5">
<!-- I am a flex items since my parent has display:flex and my inline-flex will get transformed to flex -->
<div style="display: inline-flex; line-height: 10">
<!-- I am a flex item since my parent is has display:inline-flex -->
<svg>...</svg>
</div>
</div>

line-height will have no effect here since we have no inline-level elements and no IFC (inline formatting context)

On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element. ref

and

On a non-replaced inline element, 'line-height' specifies the height that is used in the calculation of the line box height.


In the second example where you have text, the story is a bit different because you will have a flex item that will create an inline formating context for it's content.

Each in-flow child of a flex container becomes a flex item, and each contiguous sequence of child text runs is wrapped in an anonymous block container flex item. ref

So your text is wrapped inside a hidden block container and that block container will inherit the line-height and the logic of line-height will apply

Here is an illustration

<div class="block"> <!-- flexbox container -->
<span class="inline"> <!-- flex item & flexbox container -->
<anonymous> <!-- I am an anonymous block container created by the browser & a flex item and I will inherit the line-height -->
------
<anonymous>
</span>
</div>

With your SVG example, if you add a text the line-height will strike again:

svg {
width: 1rem;
height: 1rem;
}

.block {
display: flex;
border: solid 1px;
line-height: 10;
}

.inline {
display: inline-flex;
line-height: 5;
}
<div class="block">
<span class="inline">
<svg viewBox="0 0 24 24" focusable="false" xmlns="http://www.w3.org/2000/svg">
<path d="M11 7h2v2h-2zm0 4h2v6h-2z">
</path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z">
</path>
</svg> a
</span>
</div>

<div class="block">
<span class="inline">
------
</span>
</div>

How to write this styling in latest implementation of CSS3's Flexbox

The complete set of properties would look like this:

.foo {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;

-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;

-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-line-pack: center;
-webkit-align-content: center;
align-content: center;

-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
-webkit-box-direction: normal;
-moz-box-direction: normal;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}

Note that row/horizontal is the default direction, and it isn't necessary to add it unless you're overriding it from a previous column/vertical declaration elsewhere.

Setting the flex container to inline follows the same naming conventions as the other inline properties (eg. inline-block, inline-table, etc.):

.foo {
display: -webkit-inline-box;
display: -moz-inline-box;
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
}

If you're doing this specifically for vertical centering, Firefox under the 2009 implementation can sometimes be a problem because it doesn't always wrap properly. My recommendation is to use different properties for the 2009 properties compared to the modern properties like this:

http://codepen.io/cimmanon/pen/mxuFa

li {
text-align: center;
vertical-align: middle;
display: inline-block;
display: -webkit-inline-box;
display: -moz-inline-box;
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
/* vertical centering for legacy, horizontal centering for modern */
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
/* modern Flexbox only */
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
/* legacy Flexbox only */
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-box-direction: normal;
-moz-box-direction: normal;
}

Flexbox on table doesn't work in Firefox

That's because, according to CSS tables, anonymous table objects should be generated when tabular elements are not children of a table:

Sample Image

According to the Flexbox Last Call Working Draft, it was that anonymous table what became the flex item, not the table cells:

Some values of display trigger the creation of anonymous boxes
around the original box. It’s the outermost box—the direct child of
the flex container box—that becomes a flex item. For
example, given two contiguous child elements with display: table-cell, the anonymous table wrapper box generated around
them [CSS21] becomes the flex item.

Since the table cells were not flex items, they ignored the flex property. It would apply to the anonymous table, but CSS selectors can't select anonymous elements.

However, Chrome disagreed with the spec and decided to blockify the table cells instead.

Then the CSS working group decided to standardize Chrome's behavior:

If you have a flex container and you put two table cells in it, they
won't become flex items independently. They'll wrap in an anonymous
table and that will be flex.

However, Chrome had implemented it so that each item is independently
a flex item. [...] So it turns the table cells into blocks.

I've seen at least one presentation at a conference where they took
advantage of this to create fallback behavior for a flex. [...] If you're
not trying to trigger fallback, I don't know why you'd put a bunch of
table cells in flex and get it wrapped in anonymous stuff. [...]

RESOLVED: Just blockify the children of flex and grid containers.
Don't do anonymous box fix-up

The first Flexbox Candidate Recommendation was published with that new resolution:

Some values of display normally trigger the creation of
anonymous boxes around the original box. If such a box is a flex
item, it is blockified first, and so anonymous box creation will
not happen. For example, two contiguous flex items with
display: table-cell will become two separate display: block flex items, instead of being wrapped into a single
anonymous table.

And then Firefox implemented the new behavior starting at version 47 (bug 1185140).

For older versions, you can style the cells as blocks manually:

.flex-container > td {
display: block;
}

* {

box-sizing: border-box;

}

table{

border: 1px solid #ddd;

width: 100%;

}

tbody {

background: #fff;

}

tr {

display: flex;

}

td {

display: block;

}

td:first-child {

flex: 1 1 80%;

background: mistyrose;

}

td:nth-child(2){

flex: 0 0 10%;

background: Aquamarine;

}

td:nth-child(3){

flex: 0 0 10%;

background: pink;

}
<table>

<tbody>

<tr>

<td>Ted</td>

<td>1</td>

<td>100%</td>

</tr>

<tr>

<td>Turd Ferguson</td>

<td>2</td>

<td>65%</td>

</tr>

<tr>

<td>Hingle McKringleberry</td>

<td>3</td>

<td>99%</td>

</tr>

</tbody>

</table>

Trying to left-align text in a centered element

Just changed styles of .panel-body div. Also there is no need for p tag here, consider removing it from markup. Demo:

.panel {

display: flex;

border: 1px solid black;

min-height: 300px;

flex-direction: column;

max-width: 500px;

}

.panel-body {

display: flex;

flex: 1;

flex-flow: row wrap;

justify-content: center;

}

.panel-heading {

padding: 10px 10px;

}

.panel-body div.chart {

flex: 0 0 100%;

min-height: 150px;

background-color: green;

}

.panel-body div {

/* Take 33.33% width, allow grow and shrink */

flex: 1 1 33.33%;

background-color: red;

/* become a flex-container */

display: flex;

/* align flex-items vertically */

flex-direction: column;

/* center vertically */

justify-content: center;

/* center horizontally */

align-items: center;

}

p {

border: 0;

padding: 0;

margin: 0;

text-align: left;

}
<div class="panel">

<div class="panel-heading">

HEADING

</div>

<div class="panel-body">

<div class="chart"></div>

<div>

<p>HIGH

<br/>144</p>

</div>

<div>MEDIUM

<br/>2</div>

<div>LOW

<br/>3</div>

</div>

</div>


Related Topics



Leave a reply



Submit