Meek Meek - 1 month ago 279
CSS Question

Flexbox horizontal alignment: Make content fit - including pseudo element

I have a set of flexboxed divs. I would like them to adjust automatically depending on the width.
Using

flex: 1 1 auto
on the children, it seems to work for text, but not for each text's pseudo element (in this case, the arrow). What do I need to do to make the flexbox include the width of the flexbox as well?

Html:

<div class="entries">
<div class="entry">
<a href="#">Short</a>
</div>
<div class="entry">
<a href="#">Longer</a>
</div>
<div class="entry">
<a href="#">Longest</a>
</div>
<div class="entry">
<a href="#">Looooongest</a>
</div>
</div>


CSS:

.entries {
border-bottom: 1px solid #e8e8e8;
padding-bottom: 1px;
padding-top: 1px;
border-top: 1px solid #901a1e;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}

.entry {
flex: 1 1 auto;
padding: 11px 0;
width: 100%;
text-align: center;
background: #f3f3f1;
background: linear-gradient(to bottom, #f3f3f1 0%, #edece9 100%);
position: relative;
}

.entry a {
font-size: 15px;
display: inline-block;
letter-spacing: 0.06em;
line-height: 20px;
font-weight: 600;
position: relative;
text-transform: uppercase;
text-decoration: none;
color: #666;
}

.entry>a:before {
font-size: 14px;
position: absolute;
left: -18px;
top: 50%;
transform: translateY(-50%);
display: block;
color: #901a1e;
content: '>';
font-weight: 700;
}

.entry+.entry:after {
content: '';
width: 1px;
height: 70%;
position: absolute;
top: 6px;
left: 0;
background-color: #901a1e;
}


Example here - narrow the window: The arrow of the last div will disappear instead of making the first div shrink...

Answer Source

Note, the anchor and its pseudo is not part of the Flexbox itself, it is only the entries (flex container) and the entry (flex items) that are flex elements.

The reason why the arrow gets hidden is that the pseudo is absolute positioned and as such it won't be taken into account when the anchor's size is calculated (an absolute positioned element is taken out of flow), which will indirect affect how Flexbox calculate the size for the entry

If you add a left padding on a and change left to 0 on the pseudo it will work.

See notes in CSS

.entries {
  border-bottom: 1px solid #e8e8e8;
  padding-bottom: 1px;
  padding-top: 1px;
  border-top: 1px solid #901a1e;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-direction: row;
  flex-direction: row;
  -ms-flex-pack: distribute;
  justify-content: space-around;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}

.entry {
  -webkit-box-flex: 1;
  -ms-flex: 1 1 auto;
  flex: 1 1 auto;
  padding: 11px 0;
  width: 100%;
  text-align: center;
  background: #f3f3f1;
  background: -webkit-gradient(linear, left top, left bottom, from(#f3f3f1), to(#edece9));
  background: linear-gradient(to bottom, #f3f3f1 0%, #edece9 100%);
  filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#f3f3f1', endColorstr='#edece9', GradientType=0);
  position: relative;
}

.entry a {
  font-size: 15px;
  display: inline-block;
  letter-spacing: 0.06em;
  line-height: 20px;
  font-weight: 600;
  position: relative;
  text-transform: uppercase;
  text-decoration: none;
  color: #666;
  padding-left: 18px;                      /*  added  */
}

.entry>a:before {
  font-size: 14px;
  position: absolute;
  left: 0;                                 /*  changed  */
  top: 50%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
  display: block;
  color: #901a1e;
  content: '>';
  font-weight: 700;
}

.entry+.entry:after {
  content: '';
  width: 1px;
  height: 70%;
  position: absolute;
  top: 6px;
  left: 0;
  background-color: #901a1e;
}
<div class="entries">
  <div class="entry">
    <a href="#">Short</a>
  </div>
  <div class="entry">
    <a href="#">Longer</a>
  </div>
  <div class="entry">
    <a href="#">Longest</a>
  </div>
  <div class="entry">
    <a href="#">Looooongest</a>
  </div>
</div>


Since you already use Flexbox, you can use it to solve the issue you have and vertically center the text/arrow by making the anchor a a flex container.

See notes in CSS

.entries {
  border-bottom: 1px solid #e8e8e8;
  padding-bottom: 1px;
  padding-top: 1px;
  border-top: 1px solid #901a1e;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-direction: row;
  flex-direction: row;
  -ms-flex-pack: distribute;
  justify-content: space-around;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}

.entry {
  -webkit-box-flex: 1;
  -ms-flex: 1 1 auto;
  flex: 1 1 auto;
  padding: 11px 0;
  width: 100%;
  text-align: center;
  background: #f3f3f1;
  background: -webkit-gradient(linear, left top, left bottom, from(#f3f3f1), to(#edece9));
  background: linear-gradient(to bottom, #f3f3f1 0%, #edece9 100%);
  filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#f3f3f1', endColorstr='#edece9', GradientType=0);
  position: relative;
}

.entry a {
  font-size: 15px;
  display: inline-flex;                /*  added  */
  align-items: center;                 /*  added  */
  letter-spacing: 0.06em;
  line-height: 20px;
  font-weight: 600;
  position: relative;
  text-transform: uppercase;
  text-decoration: none;
  color: #666;
}

.entry>a:before {
  font-size: 14px;
  color: #901a1e;
  content: '>';
  font-weight: 700;
  padding-right: 5px;                  /*  added  */
}

.entry+.entry:after {
  content: '';
  width: 1px;
  height: 70%;
  position: absolute;
  top: 6px;
  left: 0;
  background-color: #901a1e;
}
<div class="entries">
  <div class="entry">
    <a href="#">Short</a>
  </div>
  <div class="entry">
    <a href="#">Longer</a>
  </div>
  <div class="entry">
    <a href="#">Longest</a>
  </div>
  <div class="entry">
    <a href="#">Looooongest</a>
  </div>
</div>