1

I'm trying to apply a box-shadow to tabs. The shadow should spread in every direction. I'd like to have the tab and the label in white so they appear as a homogeneous surface. My issue is that the shadow of the bottom tab element spreads to the label making the label look grayish and the border becomes visible.

:root {
  --box-shadow: 
      0 0.6px 2.2px rgba(0, 0, 0, 0.028),
      0 1.3px 5.3px rgba(0, 0, 0, 0.04),
      0 2.5px 10px rgba(0, 0, 0, 0.05),
      0 4.5px 17.9px rgba(0, 0, 0, 0.06),
      0 8.4px 33.4px rgba(0, 0, 0, 0.072),
      0 10px 40px rgba(0, 0, 0, 0.1);
}

body {
  background: #eee;
}
.tabs {
  margin: 5rem;
  width: 20rem;
}
.label {
  padding: 1rem;
  width: 33%;
  background: #fff;
  box-shadow: var(--box-shadow);
}
.tab {
  padding: 1rem;
  width: 100%;
  height: 100px;
  background: #fff;
  box-shadow: var(--box-shadow);
}
<div class="tabs">
<div class="label">
  tab 1
</div>
<div class="tab">
lorem ipsum  
</div>
</div>

The desired result should look more or less like this, except the shadow should spread to the top as well (i.e.positive y axis).

:root {
  --box-shadow: 
      0 2.8px 2.2px rgba(0, 0, 0, 0.02),
      0 6.7px 5.3px rgba(0, 0, 0, 0.028),
      0 12.5px 10px rgba(0, 0, 0, 0.035),
      0 22.3px 17.9px rgba(0, 0, 0, 0.042),
      0 41.8px 33.4px rgba(0, 0, 0, 0.05),
      0 100px 80px rgba(0, 0, 0, 0.07); 
}

body {
  background: #eee;
}
.tabs {
  margin: 5rem;
  width: 20rem;
}
.label {
  padding: 1rem;
  width: 33%;
  background: #fff;
  box-shadow: var(--box-shadow);
}
.tab {
  padding: 1rem;
  width: 100%;
  height: 100px;
  background: #fff;
  box-shadow: var(--box-shadow);
}
<div class="tabs">
<div class="label">
  tab 1
</div>
<div class="tab">
lorem ipsum  
</div>
</div>

How can I handle this?

Zin Yosrim
  • 1,602
  • 1
  • 22
  • 40

1 Answers1

2

Here's a bit of a hacky way to do it, but it works.

So first off, I'm adding position: relative and z-index: 1 to the .tab class to put it on top of the label so the label's box shadow doesn't show on top of the tab.

Second, I'm putting a pseudo-element ::after on top of the label. To do this, I put position: relative on the .label class and then set up the following element:

.label::after
{
  box-sizing: border-box;
  padding: 1rem;
  width: 100%;
  height: 100%;
  content: attr(data-content);
  background: white;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
}

So to walk through this, it's got 100% width and height to fill the .label's width and height, with the same padding as you had previously included in the .label and box-sizing: border-box to make it maintain the correct width and height. The background of course is white to match the background of the plain .label, and the position is set to absolute with top and left of 0 to put it directly on top of the label. The z-index is set to 2 so it renders on top of the box shadow from the .tab below it.

Finally, I set the content of the ::after to attr(data-content) so you can set the text inside the pseudo element to whatever you want in the HTML. It should match the text inside the .label itself so they are the same size and the cast box-shadow is the correct size.

<div class="label" data-content="tab 1">

Here's the full snippet.

:root {
  --box-shadow: 
      0 0.6px 2.2px rgba(0, 0, 0, 0.028),
      0 1.3px 5.3px rgba(0, 0, 0, 0.04),
      0 2.5px 10px rgba(0, 0, 0, 0.05),
      0 4.5px 17.9px rgba(0, 0, 0, 0.06),
      0 8.4px 33.4px rgba(0, 0, 0, 0.072),
      0 10px 40px rgba(0, 0, 0, 0.1);
}

body {
  background: #eee;
}
.tabs {
  margin: 5rem;
  width: 20rem;
}
.label {
  padding: 1rem;
  width: 33%;
  background: #fff;
  box-shadow: var(--box-shadow);
  position: relative;
}

.label::after
{
  box-sizing: border-box;
  padding: 1rem;
  width: 100%;
  height: 100%;
  content: attr(data-content);
  background: white;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
}

.tab {
  padding: 1rem;
  width: 100%;
  height: 100px;
  background: #fff;
  box-shadow: var(--box-shadow);
  position: relative;
  z-index: 1;
}
<div class="tabs">
<div class="label" data-content="tab 1">
  tab 1
</div>
<div class="tab">
lorem ipsum  
</div>
</div>
Liftoff
  • 24,717
  • 13
  • 66
  • 119