4

I tried this:

<html>
<head>
<title>Left, Mid, Right action buttons</title>
<style>
.parent {
  width: 600px;
  background-color: yellow;
}
.itemleft {
  display: flex;
  justify-content: flex-start;
}
.itemcenter {
  display: flex;
  justify-content: center;
}
.itemright {
  display: flex;
  justify-content: flex-end;
}
.bs {
  background-color: green;
  color: white;
  width: 70px;
}
</style>
</head>
<body>
  <div class="parent">
    <span class="itemleft">
      <button class="bs">Edit</button>
      <button class="bs">Delete</button>
    </span>
    <span class="itemcenter">
      <button class="bs">OK</button>
      <button class="bs">Cancel</button>
    </span>
    <span class="itemright">
      <button class="bs">Help</button>
    </span>
  </div>
</body>
</html>

Result running this in Firefox or Chrome:

  • Edit and Delete buttons are left-justified on the row
  • OK and Cancel buttons are centered on NEXT 2nd row
  • Help button is right-justified on NEXT 3rd row

I expected all buttons on the same first row first since I used span. I got same result when replacing the spans with divs.

I also tried changing 'display: flex;' to 'display inline-flex;'. Then all buttons appeared together on one row, but the justification did not work. The buttons appeared one after the other with no spaces for justification.

Have I made some mistake in the html above? Is it possible to justify the button groups by Flex only? If yes, how?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
resander
  • 1,181
  • 2
  • 11
  • 15

2 Answers2

8

When one add display: flex to each item*, it is their content that be comes flex items, not the item* themselves.

Simply add display: flex; justify-content: space-between to the parent instead, and remove the flex properties from the item*

.parent {
  display: flex;
  justify-content: space-between;
  width: 600px;
  background-color: yellow;
}
.bs {
  background-color: green;
  color: white;
  width: 70px;
}
<div class="parent">
    <span class="itemleft">
      <button class="bs">Edit</button>
      <button class="bs">Delete</button>
    </span>
    <span class="itemcenter">
      <button class="bs">OK</button>
      <button class="bs">Cancel</button>
    </span>
    <span class="itemright">
      <button class="bs">Help</button>
    </span>
  </div>

Note, as soon as you add display: flex to the span's, they become flex container and stop being normal span's. By using inline-flex they will end up on the same row, though they will stack side-by-side, sized by their content.

To achieve what you want with inline-flex, you can set each item* to be 33%, so they stretch/share the full width of their parent, though the above solution is what you should use.


Update based on a comment

To center the OK/Cancel in the middle of the parent, one can make each item* take 33.333% of the parents width by setting its flex property to flex: 1 1 0, and then center/right align the middle and right item*'s content.

The first 1 in flex: 1 1 0 tell them to flex-grow one part each (equally share), and the last 0 tell them to exclude their content before calculate their flex-grow size.

.parent {
  display: flex;
  width: 600px;
  background-color: yellow;
}
.bs {
  background-color: green;
  color: white;
  width: 70px;
}
.parent > span {
  flex: 1 1 0;
}
.parent .itemcenter {
  text-align: center;
}
.parent .itemright {
  text-align: right;
}
<div class="parent">
    <span class="itemleft">
      <button class="bs">Edit</button>
      <button class="bs">Delete</button>
    </span>
    <span class="itemcenter">
      <button class="bs">OK</button>
      <button class="bs">Cancel</button>
    </span>
    <span class="itemright">
      <button class="bs">Help</button>
    </span>
  </div>

Another option would be to set their flex-basis (last value in flex: 1 1 0) to 100% and then let them flex-shrink equally (the middle value in flex: 1 1 0), like this flex: 0 1 100%

Asons
  • 84,923
  • 12
  • 110
  • 165
  • The OK and Cancel buttons certainly are between the edge elements. To center them the left and right edge elements must have same length. If they do not, add hidden dummy button(s). In this case a dummy button before Help, '' with style .hide { visibility: hidden;}. – resander Aug 16 '17 at 16:30
  • @resander You don't need to add an element, you can use a pseudo to do that ... will add a sample to my answer – Asons Aug 16 '17 at 16:32
  • @resander Came up with a better solution...added a 2nd sample – Asons Aug 16 '17 at 16:55
  • I did not understand your 2nd example, but guessed and tried this: .parent and .bs styles and HTML part same as in your sample 1. .itemleft, itemcenter, itemright { flex: 0 1 100%;} It came out wrong with spaces after Help button and OK|Cancel not centered. Edit|Delete spaces OK|Cancel spaces Help spaces Total length 600px and length of each buttongroup + spaces 200px How should I code sample 2? – resander Aug 17 '17 at 14:20
  • @resander Here I added a dotted border around the `item*`, so you see what's going on: https://jsfiddle.net/q4h48d10/1/ – Asons Aug 17 '17 at 14:45
0

I had difficulty understanding the second solution suggested by LGSon.

So, I wrote a test that shows that the initialisation phase (flex: 0 0 100%;) produces equal-size parts (480px) on a single line with content aligned left, center and right. The length after intialisation is 3x480=1440px.

<pre>Edit Deletexxx|xxxOK Cancelxx|xxxxxxxxxxHelp
       100%             100%          100%</pre>

The shrinkage phase (0 1 100%) will consume equal amounts of gap-space around the center OK,Cancel buttons, so on completion these buttons will still be centered and the total length is 480px.

.parent00_100perc, .parent01_100perc {
  display: flex;
  width: 480px;
  background-color: yellow;
}

.spanflex00 { flex: 0 0 100%;}
.spanflex01 { flex: 0 1 100%;}

.bs {
  background-color: green;
  color: white;
  width: 70px;
}
.itemleft {
  background-color: red;
  text-align: left;
}
.itemcenter {
  background-color: cyan;
  text-align: center;
}
.itemright {
  background-color: grey;
  text-align: right;  
}


  <p>Case 1: after initialsation 0 0 100%</p> 
  <div class="parent00_100perc">
    <span class="spanflex00 itemleft">
      <button class="bs">Edit</button>
      <button class="bs">Delete</button>
    </span>
    <span class="spanflex00 itemcenter">
      <button class="bs">OK</button>
      <button class="bs">Cancel</button>
    </span>
    <span class="spanflex00 itemright">
      <button class="bs">Help</button>
    </span>
  </div>

  <p>Case 2: init then shrinking 0 1 100%</p> 
  <div class="parent01_100perc">
    <span class="spanflex01 itemleft">
      <button class="bs">Edit</button>
      <button class="bs">Delete</button>
    </span>
    <span class="spanflex01 itemcenter">
      <button class="bs">OK</button>
      <button class="bs">Cancel</button>
    </span>
    <span class="spanflex01 itemright">
      <button class="bs">Help</button>
    </span>
  </div>
resander
  • 1,181
  • 2
  • 11
  • 15