Shifted CSS Border with translucent background

Viewed 79

So I wanted to build an infinite gallery with the following layout: Expected result (the first picture also gets a border)

As you can see, only the currently active picture is visible and the inactive pictures are only indicated by their borders and the container is translucent.

Now what makes this a bit tricky, is that the borders aren't a regular rectangle but shifted to a parallelogram. To achive this I've tried the following two approaches:

Skew

My first approach was to just use CSSs transform: skewX(deg);

Sadly skew doesn't only shift but also distortes the picture..

Clip Path

with the layout as following

<div class="wrapper">
    <img></img>
</div>

Style:

.wrapper {
    clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
    background: black;
}
img {
    clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
    transform: scale(0.95);
}

I was able to spaghetti my way into a shifted border. Problem here is that when the picture isn't active anymore and should therefore be invisible, my fake border is exposed as the whole container will be black.

So I was wondering what would be the best way to shift the containers border and place the image inside so that it can be faded out and the background is translucent.

Heres a Code Snippet:

div[class*="wrapper"] {
  height: 100px;
  width: 200px;
  margin: 1em;
}

img {
  width: 100%;
  height: 100%;
}

.wrapper-clippath {
  background: black;
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
}

.wrapper-clippath img {
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
  transform: scale(0.985);
  animation: opacity 1s infinite alternate;
 }

.wrapper-skew {
  transform: skewX(-25deg);
  border: 1px solid black;
}

@keyframes opacity {
  from {
    opacity: 1;
  }
  
   to {
    opacity: 0;
  }
}
<h1>With Skew</h1>
<p>Image gets distorted</p>
<div class="wrapper-skew">
    <img src="https://www2.tuhh.de/zll/wp-content/uploads/placeholder.png">
</div>

<h1>With clippath</h1>
<p>Background is black and not translucent when image is faded out</p>
<div class="wrapper-clippath">
    <img src="https://www2.tuhh.de/zll/wp-content/uploads/placeholder.png">
</div>

1 Answers

TL-DR: In short, remove the background-color and clip-path specifications from your wrapper and create an ::after pseudo-element to place the border.


Background Color

You shouldn't specify a background color in order to achieve a border. Instead of setting your background color to black:

.wrapper-clippath {
  background: black;
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
}

Remove that specification, since the default background color is transparent:

.wrapper-clippath {
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
}

✂️ Remove the Clipping

Remove the use of clip-path on your wrapper:

.wrapper-clippath { }

There's no need for it here. Instead, it should only be specified on your img until you can justify a need for it on your wrapper:

.wrapper-clippath img {
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
  animation: opacity 1s infinite alternate;
}

Adding a Border

Since you need to add a border, it should be specified using border. This can be done by utilizing the :after pseudo-element:

In CSS, ::after creates a pseudo-element that is the last child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default.

In your case, you don't want anything in the content property. Instead, you want to create something that places a border around your clip-path:

.wrapper-clippath::after {
  content: '';
  position: absolute;
  top: 0;
  left: 25px;
  width: calc(100% - 50px);
  height: calc(100% - 2px);
  border: 1px solid black;
  transform: skewX(-25deg);
}

Additionally, to make the absolute positioning relative to your wrapper, you'll need to mark your wrapper-clippath class as having relative positioning:

.wrapper-clippath { position: relative; }

✔️ Result

div[class*="wrapper"] {
  height: 100px;
  width: 200px;
  margin: 1em;
}
img {
  width: 100%;
  height: 100%;
}
.wrapper-clippath {
  position: relative;
}
.wrapper-clippath:after {
  content: '';
  position: absolute;
  top: 0;
  left: 25px;
  width: calc(100% - 50px);
  height: calc(100% - 2px);
  border: 1px solid black;
  transform: skewX(-25deg);
}
.wrapper-clippath img {
  clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
  animation: opacity 1s infinite alternate;
}
@keyframes opacity {
  from {
    opacity: 1;
  }
  
   to {
    opacity: 0;
  }
}
<div class="wrapper-clippath">
<img src="https://www2.tuhh.de/zll/wp-content/uploads/placeholder.png">
</div>

Related