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

Time:01-28

I have a header on my website, which uses display: flex. Inside it, there are three elements, a heading, an image (nested inside a div so that I can make use of a certain type of CSS image filtering) and a vertical nav.

The heading and nav have flex: 0, whereas the image has flex: 1, so it gets bigger as my display gets wider, as intended.

The nav items have a ::before pseudo element that appears on hover. When it appears, it takes up space and so my image shrinks varying amounts when I over over the nav items and it makes my page look glitchy. How can I make it so that the ::before pseudo element does not make the image shrink when it appears? Is this even possible? Or do I need to switch to using an actual element that gets made visible when I hover?

I have tried using absolute positioning on the ::before element but then when I try to move it using the left property, it disappears.

https://codepen.io/pen/?template=BamyEYW

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.selected::before {
  content: '> ';
  color: rgba(0, 0, 0, 0.6);
}

nav ul li.internal-nav:hover::before {
  content: '> ';
  color: red;
}

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;
}
<header>
  <h1>Page Title</h1>
  <div ><img src="MyPhoto.jpeg" /></div>
  <nav>
    <ul>
      <li ><a href="#about-me">About Me</a></li>
      <li ><a href="#experience">Experience</a></li>
      <li ><a href="#lab">Lab</a></li>
    </ul>
  </nav>
</header>

CodePudding user response:

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 ><img src="https://images.dog.ceo/breeds/collie-border/n02106166_2345.jpg"></div>
    
    <nav>
      <ul>
        <li ><a href="#">About Dogs</a></li>
        <li ><a href="#">My Fav Dogs</a></li>
        <li ><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>

CodePudding user response:

The core issue here is:

  • The size of the image depends on the width of the nav
  • The width of the nav changes

One of those has to go.
I'm assuming you want to keep the first and remove the second.

You can't make a ::before-element take up space when the style that creates it is not enganged, so the remaining (simple) strategies I can think of are:

  1. Reserve space for the marker all the time (as you suggest in your answer)
  2. Make the marker take up space all the time (as you suggest in your question)
  3. Make the marker take up no space all the time (like @yaroslav-trach suggests)

#1 lets you continue to base it on ::before, but is a bit brittle since it involves guesswork/knowledge of font witdth etc.
#2 is very robust, and can still be done in pure css.
#3 is in between: you still need to get the width right, but if you miss it only affects the look of the marker, not the rest of the layout

CodePudding user response:

Seeing as the nav items are unlikely to change, or if they change they will change to set values, it is fine to set the min-width of the nav to leave enough space for the ::before pseudo element, e.g. min-width: 12em.

CodePudding user response:

add a max-width: (suggesting 65rem) to profile-photo3 to stop the photo shrinking the max width will never get larger than the appointed size though.

  •  Tags:  
  • Related