Search code examples
htmlcssclip-path

Weird artefact showing behind only one of before/after pseudo selector in my breadcrumbs


I am trying to create 3 section breadcrumbs type element with an arrow divider. This is a simple mockup.

There is a weird artefact showing between section 2 and 3. In this case section three's red background is visible (slightly) to the left of the blue arrow of section 2, however the same problem doesn't occur with section 2's background interfering with section 1 arrow. thankfully but weirdly. For me this is only happening on Chrome for Mac too (the browser window isn't zoomed in/out either). Haven't tested Windows etc. Any suggestions as to how to fix this bizarre issue?

weird artefact

A zoomed up view of the weird artefact (the red vertical line) occurring between section 2 and 3:

weird artefact zoomed

No such weird artefact occurs between section 1 and 2.

The codepen:

https://codepen.io/reacting/pen/xeewdO

The html:

<div class="container">
  <div class="section">section one</div>
  <div class="section two">section two</div>  
  <div class="section">section three</div> 
</div>

The css/scss:

.container {
  background-color: white;
  border: 1px solid grey;
  box-sizing: border-box;
  width: 100%;
  display: flex;
}
.section {
  flex: 1;
  position: relative;
  height: 100px;
  background-color: black;
  color: white;
  display: flex;
  justify-content: center;
  align-items: center;
  &:before {
    content:"";
    background-color: grey;
    -webkit-clip-path: polygon(0% 100%, 100% 50%, 0% 0%);
    clip-path: polygon(0% 100%, 100% 50%, 0% 0%);
    z-index: 1;
    position: absolute;
    right: -26px;
    top: 0;
    width: 25px;
      height: 100px;
  }
  &:after {
    content:"";
    background-color:black;
     -webkit-clip-path: polygon(0% 100%, 100% 50%, 0% 0%);
    clip-path: polygon(0% 100%, 100% 50%, 0% 0%);
    z-index: 2;
    position: absolute;
    right: -25px;
    top: 0;
    width: 25px;
    height: 100px;
  }
  &:last-of-type {
    background-color: red;
    color: black;
  }
  &:last-of-type:before {
   display: none;
  }
  &:last-of-type:after {
   display: none;
  }
  &.two {
   background-color: blue;
    &:after {
      background-color: blue;
    }
  }
}

body {
  background-color: #333;
}

I don't just want to change the right: attribute of the before/after pseudo selectors to be less 1 pixel as that just feels hacky and wrong.

Many thanks!

Edit: I wonder if the issue is related to the high resolution of my Mac display - as when I resize the chrome browser window slightly the problem comes and goes and changes to occur for section 1/2 or both section 1/2 and 2/3 or none. depending on the size of the browser window. But strangely in Firefox and Safari this doesn't occur when dragging the window at all.


Solution

  • You can optimize the code and consider clip-path on the element without the need of pseudo element then consider some background coloration to simulate the border

    .container {
      background-color: white;
      border: 1px solid grey;
      box-sizing: border-box;
      display: flex;
      height: 100px;
    }
    
    .section {
      flex: 1;
      color: white;
      display: flex;
      justify-content: center;
      align-items: center;
      margin-left:-25px; /* Create an overlap with the previous element */
      /* the clip path (note the 25px that is the same as margin*/
      -webkit-clip-path: polygon(100% 0, 100% 50%, 100% 100%, 0% 100%, 25px 50%, 0% 0%);
      clip-path: polygon(100% 0, 100% 50%, 100% 100%, 0% 100%, 25px 50%, 0% 0%);
      /* the border (note the 25px in the gradient)*/
      border-left:3px solid grey; /* this will push the background and control the thickness of the border*/
      background:
        linear-gradient(to top right,    grey 48%,transparent 50%) top left   /25px 50%,
        linear-gradient(to bottom right, grey 48%,transparent 50%) bottom left/25px 50%;
      background-repeat:no-repeat;
      background-color: black;
    }
    .section:last-of-type {
      background-color: red;
      color: black;
    }
    .section:first-of-type {
      /* Remove everything from the first element */
      clip-path:none; 
      margin-left:0;
      border-left:0;
      background:black;
    }
    .section.two {
      background-color: blue;
    }
    
    body {
      background-color: #333;
    }
    <div class="container">
      <div class="section">section one</div>
      <div class="section two">section two</div>
      <div class="section">section three</div> 
    </div>