Meek
Meek

Reputation: 3362

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...

Upvotes: 0

Views: 96

Answers (2)

Asons
Asons

Reputation: 87231

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>

Upvotes: 2

Michael Benjamin
Michael Benjamin

Reputation: 371669

A pseudo-element in a flex container is a flex item.

A flex item that is absolutely-positioned is removed from the document flow and no longer accepts flex properties.

So if you want your pseudo item to behave like the DOM items, don't use absolute positioning.

https://www.w3.org/TR/css-flexbox-1/#abspos-items

Upvotes: 1

Related Questions