How do I wrap a box-shadow around a cluster of flex items

Viewed 51

I have a bunch of pill-like items that have flexed elements inside. I'd like to wrap the entire "pill" in a box-shadow, but I'm fighting the blocky div that defines the flex.

I've tried playing with inline-flex inside individual divs, but that broke the uniformity of each "pill" having the same width for each section.

In the code below, I have two examples of what I've tried with the box shadow: attaching it to the flex container and attaching it to the individual flex items.

https://codepen.io/rewing/pen/oNdZNxb

HTML and CSS

.box-shadow-test-1 {
  -webkit-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  border-radius: 10px;
}

.box-shadow-test-2>div {
  -webkit-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
}

.thing {
  display: flex;
  gap: 0;
  margin-bottom: 10px;
  font-size: 14px;
  cursor: default;
}
.thing > div {
  padding: 10px;
  border-top: 1px solid #666;
  border-bottom: 1px solid #666;
}
.thing .indicator {
  border-left: 1px solid #666;
  border-right: 1px solid #666;
}
.thing .left-indicator {
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
  padding-top: 18px;
  flex-basis: 13px;
}
.thing .left-indicator.state-1 {
  background-color: #bff2c6;
}
.thing .left-indicator.state-2 {
  background-color: #AAA;
}
.thing .left-indicator.state-3 {
  background-color: #bff2c6;
}
.thing .left-indicator.state-4 {
  background-color: #ff8989;
}
.thing .name {
  background-color: #FFFFFF;
  flex-basis: 195px;
}
.thing .change {
  background-color: #FFFFFF;
  flex-basis: 135px;
  padding-top: 18px;
}
.thing .right-indicator {
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
  padding-top: 18px;
}
.thing .right-indicator.state-1 {
  background-color: #bff2c6;
  cursor: pointer;
}
.thing .right-indicator.state-1:hover {
  background-color: #A6D9AD;
}
.thing .right-indicator.state-2 {
  background-color: #AAA;
}
.thing .right-indicator.state-3 {
  background-color: #fcf95c;
  cursor: pointer;
}
.thing .right-indicator.state-3:hover {
  background-color: #E3E043;
}
.thing .right-indicator.state-4 {
  background-color: #FFFFFF;
}
<div class="things">
   <div class="cluster">
      <div class="thing box-shadow-test-1">
         <div class="indicator left-indicator state-2">&nbsp;</div>
         <div class="name">Name 1</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-2">state-2</div>
      </div>
      <div class="thing thing-2 box-shadow-test-2">
         <div class="indicator left-indicator state-2">&nbsp;</div>
         <div class="name">Name 2</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-2">state-2</div>
      </div>
     <div class="thing thing-3">
         <div class="indicator left-indicator state-3">&nbsp;</div>
         <div class="name">Name 3</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-3">state-3 longer</div>
      </div>
     <div class="thing thing-4">
         <div class="indicator left-indicator state-4">&nbsp;</div>
         <div class="name">Name 4</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-4">state-4 short</div>
      </div>
   </div>
</div>

Edit:

For clarification, the third box shadow'd pill in this list is what I'm trying to create. The first attempt is wrapped around the blocky div, the second attempt shows the box-shadow inside the pill itself, but the third (photoshopped) pill has the box-shadow only around the outside of the flex container.

enter image description here

2 Answers

One approach is as below, with explanatory comments in the code:

:root {
 --shadowColor: hsl(0deg 20% 20% / 0.7);
}

.thing {
  display: flex;
  align-content: center;
  gap: 0;
  margin-bottom: 10px;
  font-size: 14px;
  cursor: default;
}

.thing>div {
  padding: 10px;
  border-top: 1px solid #666;
  border-bottom: 1px solid #666;
}

.thing .indicator {
  border-left: 1px solid #666;
  border-right: 1px solid #666;
}

.thing .left-indicator {
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
  flex-basis: 13px;
}

.thing .left-indicator.state-3 {
  background-color: #bff2c6;
}

.thing .name {
  background-color: #FFFFFF;
  flex-basis: 195px;
}

.thing .change {
  background-color: #FFFFFF;
  flex-basis: 135px;
}

.thing .right-indicator {
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

.thing .right-indicator.state-3 {
  background-color: #fcf95c;
  cursor: pointer;
}

.thing .right-indicator.state-3:hover {
  background-color: #E3E043;
}

.withShadow {
  /* using the 'filter' property to apply a drop-shadow, using the
     drop-shadow() function:
      (first) 0:          the x-offset (positive numbers moves to the right,
                          negative to the left),
      (second) 0:         the y-offset (positive numbers move down, negative
                          numbers go up),
      0.5em:              the spread of the colour,
      var(--shadowColor): the colour of the shadow (here using a CSS property)
     */
  filter: drop-shadow(0 0 0.5em var(--shadowColor));
}
<!-- for brevity I removed all but the one element you said you wanted to have the shadow
     (and, similarly, removed the unnecessary CSS for the removed elements): -->
<div class="things">
    <!-- I added a single class-name 'withShadow' to apply the CSS (because I was unsure of
         the situations in which you wanted the shadow added; obviously you can add the
         CSS declarations to another class if it makes more sense: -->
    <div class="thing thing-3 withShadow">
      <div class="indicator left-indicator state-3">&nbsp;</div>
      <div class="name">Name 3</div>
      <div class="change">Property 1</div>
      <div class="indicator right-indicator state-3">state-3 longer</div>
    </div>
</div>

JS Fiddle demo.

References:

Try adding filter: drop-shadow(0 0 3px rgb(0 0 0 / 75%)); in the .thing-3 class

.box-shadow-test-1 {
  -webkit-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  border-radius: 10px;
}

.box-shadow-test-2>div {
  -webkit-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
  box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.75);
}

.thing {
  display: flex;
  gap: 0;
  margin-bottom: 10px;
  font-size: 14px;
  cursor: default;
}

.thing-3 {
  filter: drop-shadow(0 0 3px rgb(0 0 0 / 75%));
}

.thing > div {
  padding: 10px;
  border-top: 1px solid #666;
  border-bottom: 1px solid #666;
}
.thing .indicator {
  border-left: 1px solid #666;
  border-right: 1px solid #666;
}
.thing .left-indicator {
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
  padding-top: 18px;
  flex-basis: 13px;
}
.thing .left-indicator.state-1 {
  background-color: #bff2c6;
}
.thing .left-indicator.state-2 {
  background-color: #AAA;
}
.thing .left-indicator.state-3 {
  background-color: #bff2c6;
}
.thing .left-indicator.state-4 {
  background-color: #ff8989;
}
.thing .name {
  background-color: #FFFFFF;
  flex-basis: 195px;
}
.thing .change {
  background-color: #FFFFFF;
  flex-basis: 135px;
  padding-top: 18px;
}
.thing .right-indicator {
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
  padding-top: 18px;
}
.thing .right-indicator.state-1 {
  background-color: #bff2c6;
  cursor: pointer;
}
.thing .right-indicator.state-1:hover {
  background-color: #A6D9AD;
}
.thing .right-indicator.state-2 {
  background-color: #AAA;
}
.thing .right-indicator.state-3 {
  background-color: #fcf95c;
  cursor: pointer;
}
.thing .right-indicator.state-3:hover {
  background-color: #E3E043;
}
.thing .right-indicator.state-4 {
  background-color: #FFFFFF;
}
<div class="things">
   <div class="cluster">
      <div class="thing box-shadow-test-1">
         <div class="indicator left-indicator state-2">&nbsp;</div>
         <div class="name">Name 1</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-2">state-2</div>
      </div>
      <div class="thing thing-2 box-shadow-test-2">
         <div class="indicator left-indicator state-2">&nbsp;</div>
         <div class="name">Name 2</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-2">state-2</div>
      </div>
     <div class="thing thing-3">
         <div class="indicator left-indicator state-3">&nbsp;</div>
         <div class="name">Name 3</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-3">state-3 longer</div>
      </div>
     <div class="thing thing-4">
         <div class="indicator left-indicator state-4">&nbsp;</div>
         <div class="name">Name 4</div>
         <div class="change">Property 1</div>
         <div class="indicator right-indicator state-4">state-4 short</div>
      </div>
   </div>
</div>

Related