1

I am trying to achieve the equivalent of floats with Flexbox.

I'm succeeding if there is only one element pushed to the right, but failing when there are multiple elements that need to be floated right, unless worked around with the general sibling selector (~).

Attempt #1:

Failing as the red block should be on the right

.block {
  display: flex;
  margin: -5px;
}
.block__element {
  background: #ddd;
  padding: 5px;
  margin: 0 5px;
}
.block__element--first {
  order: -1;
}
.block__element--right {
  margin-left: auto;
}
.u-error {
  background: #ce0e0e;
  color: #fff;
}
<div class="block">
  <div class="block__element">random elem</div>
  <div class="block__element block__element--right u-error">right elem</div>
  <div class="block__element block__element--first">first elem</div>
  <div class="block__element block__element--right">right elem</div>
</div>

Attempt #2:

Uses the general sibling selector (~) so relies on markup order, will not work if the order is modified using order.

.block {
  display: flex;
  margin: -5px;
}
.block__element {
  background: #ddd;
  padding: 5px;
  margin: 0 5px;
}
.block__element--first {
  order: -1;
}
.block__element--right {
  margin-left: auto;
}
.u-error {
  background: #ce0e0e;
  color: #fff;
}
<div class="block">
  <div class="block__element">random elem</div>
  <div class="block__element block__element--right u-error">right elem</div>
  <div class="block__element block__element--first">first elem</div>
  <div class="block__element block__element--right">right elem</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
veksen
  • 6,863
  • 5
  • 20
  • 33
  • Not quite sure either. [But shouldn't you](http://stackoverflow.com/questions/22429003/right-aligning-flex-item) just be able to use a `margin-left: auto` on the first element you want to "float"? EDIT: just confirmed, yes you can – vladdobra Oct 17 '16 at 21:35
  • @vladdobra yes, this is what i'm doing already, but I do not know which one is the first element (markup is dynamic), which was covered with my attempt #2 – veksen Oct 17 '16 at 21:37
  • @veksen I'm confused, did you use the `~` selector? It does work if you use it like [**this**](https://jsfiddle.net/rickyruizm/hnzfe37x/) – Ricky Ruiz Oct 17 '16 at 22:04
  • @Ricky_Ruiz not when combined with `order`: https://jsfiddle.net/hnzfe37x/1/ – veksen Oct 17 '16 at 22:06
  • @veksen Then you should do what Michael suggested. Be aware of the accessibility issues using `order` brings into the table. – Ricky Ruiz Oct 17 '16 at 22:10
  • @Ricky_Ruiz it's working as intended, as `~` selects the next sibling elements, but the "starting" selector was reordered. – veksen Oct 17 '16 at 22:20

1 Answers1

3

I think the key is not to use margin-left: auto on the items you want positioned to the right. As you can see, that spaces them away from each other.

Instead, use margin-right: auto on the right-most item of the left section. That will push everything else to the right.

.block > div:first-child { margin-right: auto; }
/* The actual left-section right-most item has order:-1, so the selector above
   ends up targeting the proper item. */

.block {
  display: flex;
  margin: -5px;
}
.block__element {
  background: #ddd;
  padding: 5px;
  margin: 0 5px;
}
.block__element--first {
  order: -1;
}
.block__element--right {} .u-error {
  background: #ce0e0e;
  color: #fff;
}
<div class="block">
  <div class="block__element">random elem</div>
  <div class="block__element block__element--right u-error">right elem</div>
  <div class="block__element block__element--first">first elem</div>
  <div class="block__element block__element--right">right elem</div>
</div>

Another option to consider would be to use a pseudo-element that inserts an invisible flex item between the left and right sections, giving this item flex: 1.

.block::after {
  content: "spacer element";
  background: #ddd;
  padding: 5px;
  margin: 0 5px;
  flex: 1;
  visibility: hidden; /* disable this rule to see the item at work */
}
.block {
  display: flex;
  margin: -5px;
}
.block__element {
  background: #ddd;
  padding: 5px;
  margin: 0 5px;
}
.block__element--first {
  order: -1;
}
.block__element--right {
  order: 2;
}
.u-error {
  background: #ce0e0e;
  color: #fff;
}
<div class="block">
  <div class="block__element">random elem</div>
  <div class="block__element block__element--right u-error">right elem</div>
  <div class="block__element block__element--first">first elem</div>
  <div class="block__element block__element--right">right elem</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701