Pseudo Elements Breaking Justify-Content: Space-Between in Flexbox Layout

Pseudo elements breaking justify-content: space-between in flexbox layout

Short Answer

In CSS, there is currently no 100% reliable way to prevent pseudo-elements from impacting the justify-content: space-between calculation.

Explanation

::before and ::after pseudo elements on a flex container become flex items.

From the spec:

4. Flex Items

Each in-flow child of a flex container becomes a flex item.

In other words, each child of a flex container that is in the normal flow (i.e., not absolutely positioned), is considered a flex item.

Most, if not all, browsers interpret this to include pseudo-elements. The ::before pseudo is the first flex item. The ::after item is the last.

Here is further confirmation of this rendering behavior from Firefox documentation:

In-flow ::after and ::before pseudo-elements are now flex
items
(bug 867454).

One possible solution to your problem is to remove the pseudo-elements from the normal flow with absolute positioning. However, this method may not work in all browsers:

  • Absolutely positioned flex item is not removed from normal flow in Firefox & IE11

See my answer here for illustrations of pseudo elements messing up justify-content:

  • justify-content: space-between failing to align elements as expected

justify-content: space-between failing to align elements as expected

The problem is a conflict with the Bootstrap stylesheet, which places pseudo-elements in your flex container. This causes space-between to calculate multiple flex items as opposed to just two.

Here's your flex container:

The logo and nav menu are aligned with justify-content: space-between, but are not positioned at opposite edges. The alignment looks more like space-around.

Sample Image


Here's Bootstrap's ::before and ::after pseudo-elements (or pseudo-flex items):

As noted in Firefox documentation:

In-flow ::after and ::before pseudo-elements are flex items.

Sample Image


Let's put some content in the pseudos:

Like shining a black light in a motel room, you see a lot of stuff you wish wasn't there.

Sample Image


Remove (or override) the pseudo-elements and your problem is gone:

Sample Image


More details about flex containers and pseudo-elements:

  • Pseudo elements breaking justify-content: space-between in flexbox layout
  • Properly sizing and aligning the flex item(s) on the last row
  • Methods for Aligning Flex Items along the Main Axis (see Box #81)

How can I prevent the ::before pseudo element from affecting my flex layout?

You can update your pseudo element, like this:

nav ul li.internal-nav.selected a:before,
nav ul li.internal-nav a:hover:before {
content: '> ';
position: absolute;
left: -1rem;
color: red;
}

nav ul li.internal-nav.selected a:before {
opacity: .6;
}

Run code snippet and open it on fullpage to see changes.
Also you can check it here (Codepen.io)

header {
margin-block-start: 3em;
padding-bottom: 0.67rem;
padding-left: 5%;
padding-right: 5%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}

nav {
margin-left: auto;
}

nav ul {
list-style: none;
display: flex;
flex-direction: column;
padding-inline-start: 0;
padding-left: 1em;
}

nav ul li {
text-align: right;
font-size: x-large;
}

nav ul li a:hover {
color: red;
}

nav ul li.internal-nav a {
position: relative;
}

nav ul li.internal-nav.selected a:before,
nav ul li.internal-nav a:hover:before {
content: '> ';
position: absolute;
left: -1rem;
color: red;
}

nav ul li.internal-nav.selected a:before {
opacity: .6;
}

h1 {
color: rgba(0, 0, 0, 0.6);
font-size: 5em;
}

.profile-photo3 {
position: relative;
flex: 1;
min-width: 20rem;
background-color: blue;
clip-path: polygon(70% 0%, 100% 50%, 70% 100%, 0% 70%, 20% 15%);
}

.profile-photo3 img {
width: 100%;
mix-blend-mode: screen;
}
<head>
<script src="https://cpwebassets.codepen.io/assets/editor/iframe/iframeConsoleRunner-d0f3648046d2aaca07bd0037b9e061a26c74a8a999b75672ad6a638cca641472.js"></script>
<script src="https://cpwebassets.codepen.io/assets/editor/iframe/iframeRefreshCSS-4793b73c6332f7f14a9b6bba5d5e62748e9d1bd0b5c52d7af6376f3d1c625d7e.js"></script>
<script src="https://cpwebassets.codepen.io/assets/editor/iframe/iframeRuntimeErrors-4f205f2c14e769b448bcf477de2938c681660d5038bc464e3700256713ebe261.js"></script>
</head>

<body>
<header>
<h1>Dogs :)</h1>

<div class="profile-photo3"><img src="https://images.dog.ceo/breeds/collie-border/n02106166_2345.jpg"></div>

<nav>
<ul>
<li class="internal-nav"><a href="#">About Dogs</a></li>
<li class="internal-nav selected"><a href="#">My Fav Dogs</a></li>
<li class="internal-nav"><a href="#">Dog Facts</a></li>
</ul>
</nav>
</header>

<script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-1b93190375e9ccc259df3a57c1abc0e64599724ae30d7ea4c6877eb615f89387.js"></script>
<script src="https://cdpn.io/cp/internal/boomboom/pen.js?key=pen.js-f2136278-4370-4b42-10b9-cde5fe228f8b" crossorigin=""></script>
</body>

How to specify line breaks in a multi-line flexbox layout?

The simplest and most reliable solution is inserting flex items at the right places. If they are wide enough (width: 100%), they will force a line break.

.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(4n - 1) {
background: silver;
}
.line-break {
width: 100%;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="line-break"></div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="line-break"></div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="line-break"></div>
<div class="item">10</div>
</div>

Breaks the flexbox layout when I wrapped the divs with a

just change the div to a <a> like this

.container{
position: absolute;
left:0;
top: 0;
width:100%;
height: 30px;
}

.flex_container{
display: flex;
justify-content: space-around;
}

.box{
background: silver;
width: 25%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid black;
}
<header>
<div class="container flex_container">
<a href="#" class="box">link1</a>
<a href="#" class="box">link2</a>
<a href="#" class="box">link3</a>
<a href="#" class="box">link4</a>
</div>
</header>

flex justify-content:space-between not working

Add .textwidget::before, .textwidget::after { content: none; }. You have content: "" added in line 1341 for this element and it breaks flex. Or just remove .textwidget::before, .textwidget::after from line 1341 ;)

Other ways to justify-content: space-between?

You may use margin instead align-items and/or justify-content.

example:

not sure you looked for space-between or space-around, so i put both margin alternative

div div {  box-sizing: border-box;  border: solid;}
.cards-list { display: flex; flex-direction: row; flex-wrap: wrap; align-items: flex-start;/* will not spray the entire row */}
.cards-list .card-item { margin-bottom: 15px; flex-basis: 49%; padding: 30px 45px; margin: 0 auto 15px;}
.cards-list .card-item-small { flex-basis: 25%;}
div div:before { content: attr(class);}
.cards-list.bis .card-item { margin: 0 0 15px; /* reset for demo*/ color: darkblue;}
.cards-list.bis .card-item:nth-child(2n) { margin-left: auto;}
<div class="cards-list">  <div class="card-item"></div>  <div class="card-item"></div>  <div class="card-item-small"></div>  <div class="card-item-small"></div>  <div class="card-item-small"></div>  <div class="card-item-small"></div></div><hr><div class="cards-list">  <div class="card-item-small"></div>  <div class="card-item-small"></div>  <div class="card-item"></div></div><hr><div class="cards-list bis">  <div class="card-item"></div>  <div class="card-item"></div>  <div class="card-item"></div>  <div class="card-item"></div></div>

Why does space-around allow flex items to overflow on the left side?

Since the container is limited in width and you want overflowing flex items to be accessed via horizontal scrolling, why use justify-content: space-around?

Try justify-content: flex-start:

Revised Codepen

To understand why overflowing flex items may be inaccessible via scroll, see this answer.

If you're interested in a Javascript workaround for the original code, see this post:

  • When centering horizontally, li's get cut off


Related Topics



Leave a reply



Submit