4lackof 4lackof - 3 months ago 9
jQuery Question

Using 'order' property to position flex item between siblings

I have a flex-box with one to three flex-items.

The proper layout should look like

<div></div><h2></h2><div></div>
in the containing flex-box.

I have code to make this work (see this) only if the layout order stays the same.


My question is: how is there a way to make sure, if the markup is not always in that order (say one of my co-workers fails to do it correctly), how can I set it so that the
<h2>
always gets displayed in the middle (or as close as possible in the case that there are only one div and one h2).


To accomplish this I have been making use of the
order
property; however, I am either not using it to its full potential or it is the wrong solution.

I have made this jsfiddle as a testing ground for it but there is also this sample:

.diff-order {
order: 2
}
.diff-order:not(h2) {
order: 1;
}




.container {
display: flex;
}
.container > * {
flex: 1; /* KEY RULE */
border: 1px dashed red;
}
h2 {
text-align: center;
margin: 0;
}
.container > div {
display: flex;
}
.diff-order {
order: 2
}
.diff-order:not(h2) {
order: 1;
}
p { text-align: center;}
p > span { background-color: aqua; padding: 5px; }

<div class="container">
<h2>
I'm an h2
</h2>
<div>
<span>I'm a span</span>
<span>I'm a span</span>
</div>
<div>
<span>I'm a span</span>
<span>I'm a span</span>
</div>
</div>
<div class="container">
<h2 class="diff-order">
I'm an h2
</h2>
<div class="diff-order">
<span>I'm a span</span>
<span>I'm a span</span>
</div>
<div class="diff-order">
<span>I'm a span</span>
<span>I'm a span</span>
</div>
</div>





What it accomplishes is it moves the
<h2>
to the end of the containing div. I am trying to see if there is a way to set the order so that
<h2>
will always be the center item.
Maybe the pseudo-classes
:before
and
:after
can be utilized (maybe as replacements for the div's around the h2...).

Thank you.

Answer

When there are three elements in the container:

  • div
  • h2
  • div

AND

  • the order of these elements varies in the source...

AND

  • you want the h2 to always be in the middle...

THEN, you can do something like this:

.container > div:first-of-type { order: 1; }
.container > h2 { order: 2; }
.container > div:last-of-type { order: 3; }

This basically says:

Regardless of the order of elements in the source,

  • The first div will appear first in the visual order
  • The h2 will appear second in the visual order
  • The second div will appear last in the visual order

.container {
  display: flex;
}
.container > * {
  flex: 1;
  border: 1px dashed red;
}
h2 { 
  text-align: center;
  margin: 0;
}

.container > div:first-of-type { order: 1; }
.container > h2 { order: 2; }
.container > div:last-of-type { order: 3; }

p { text-align: center;}
p > span { background-color: aqua; padding: 5px; }
<div class="container">
  <div>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
</div>
<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 4</span>
    <span>I'm span 5</span>
    <span>I'm span 6</span>
  </div>
</div>
<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 3</span>
  </div>
</div>
<div class="container">
  <div>
    <span>I'm a span</span>
    <span>I'm a span</span>
  </div>
  <div>

  </div>
  <h2>
    I'm an h2
  </h2>
</div>
<div class="container">
  <div>
    <span>I'm a span</span>
    <span>I'm a span</span>
  </div>
  <h2>
    I'm an h2
  </h2>
</div>
<div class="container">
  <h2 class="diff-order">
    I'm an h2
  </h2>
  <div class="diff-order">
    <span>I'm a span</span>
    <span>I'm a span</span>
  </div>
  <div class="diff-order">
    <span>I'm a span</span>
    <span>I'm a span</span>
  </div>
</div>
<p><span>TRUE CENTER</span></p>


When there is three elements in the container: