Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure CSS solution to add multiple box shadows dynamically

Tags:

javascript

css

I'm looking to achieve this multiple underline effect and figured out that using box-shadows would be the best way to do it. Specifically, I tried doing this and was successful:

enter image description here

I used the following CSS to do it:

h1{
    box-shadow: 0 2px 0px 0px #F03A47, 0 4px 0px 0px #FFF, 0 6px 0px #276FBF, 0 8px 0px 0px #FFF, 0 10px 0px #AF5B5B;
    float: left;
}

However, I'd like to achieve an effect to turn specific underlines on and off as required. So I came up with this and added the classes to my HTML:

h1{
    float: left;
}
.red{
    box-shadow: 0 2px 0px 0px #F03A47, 0 4px 0px 0px #FFF;
}
.blue{
    box-shadow: 0 6px 0px #276FBF, 0 8px 0px 0px #FFF;
}
.brown{
    box-shadow: 0 10px 0px #AF5B5B, 0 12px 0px 0px #FFF;
}

But the effect that it produced was this:

enter image description here

I tried adding the classes in different orders and also adding them dynamically using JavaScript, but I am still getting the same result. Am I doing anything wrong, or is there an alternative way to achieve the turn-on turn-off effect?

like image 409
Gautam Krishnan Avatar asked Jun 27 '17 19:06

Gautam Krishnan


4 Answers

This could be accomplished with pseudo elements:

h1 {
  display:inline-block;
  border-bottom:2px solid #e8353b;
  position:relative;
}
  h1:before {
    content:"";
    height:2px;
    width:100%;
    background:#2762be;
    display:block;
    position:absolute;
    bottom:-6px;
  }
  h1:after {
    content:"";
    height:2px;
    width:100%;
    background:#a3514f;
    display:block;
    position:absolute;
    bottom:-10px;
  }
<h1>Hello there</h1>
like image 172
APAD1 Avatar answered Oct 27 '22 20:10

APAD1


An interesting way using <span>s :)

You can add as many <span> as you want and just extend the colors palette in CSS:

.borders {
  display: inline-block;
}
.borders span {
  display: block;
  height: 2px;
  margin: 2px;
}
.borders span:nth-child(1) { background: red; }
.borders span:nth-child(2) { background: blue; }
.borders span:nth-child(3) { background: green; }
/* Add more here */
<h1 class="borders">
  Hi there
  <span></span>
  <span></span>
  <span></span>
</h1>

Or if you need only 3 borders and you don't want to insert additional HTML elements:

use a border-bottom for your first class, than :before on your second class and :after on your third class.

h1 {
  position: relative;
  display: inline-block;
}

.red{
  box-shadow: 0 2px 0 red;
}

.blue:after, .green:before{ content: ""; position: absolute; width: 100%; left: 0; }

.blue:after{
  bottom: -6px;
  border-bottom: 2px solid blue;
}

.green:before{
  bottom: -10px;
  border-bottom: 2px solid green;
}
<h1 class="red blue green">Hi there</h1>
like image 28
Roko C. Buljan Avatar answered Oct 27 '22 20:10

Roko C. Buljan


You can use linear-gradient, which will be fully transparent.

Note, when combine classes as you did, they doesn't merge those values, the last property set on an element will overwrite any previous, whether they are set in classes with different names or not, hence your line becomes all brown.

body {
  background: lightgray
}

h1{
    float: left;
    padding-bottom: 8px;
    background-size: 100% 2px;                         /* thickness 2px */
    background-repeat: no-repeat;
    background-position: 
      left bottom, left bottom 4px, left bottom 8px;   /* gutter 2px */ 
    background-image:
      linear-gradient(to right, blue, blue),           /* bottom line */
      linear-gradient(to right, green, green),         /* middle line */
      linear-gradient(to right, red, red);             /* top line */
  }
  
h1.red{
    background-image:
      linear-gradient(to right, blue, blue), 
      linear-gradient(to right, green, green),      
      linear-gradient(to right, transparent,transparent);
}
h1.blue{
    background-image:
      linear-gradient(to right, transparent,transparent),
      linear-gradient(to right, green, green),      
      linear-gradient(to right, red, red);      
}
h1.green{
    background-image:
      linear-gradient(to right, blue, blue), 
      linear-gradient(to right, transparent,transparent),
      linear-gradient(to right, red, red);      
}
<h1>Hello there</h1>

<h1 class="green">Hello there</h1>

<h1 class="red">Hello there</h1>

<h1 class="blue">Hello there</h1>

You can easily re-position the lines and close any gap by simply leave out the line you don't want.

body {
  background: lightgray
}

h1{
    float: left;
    padding-bottom: 8px;
    background-size: 100% 2px;                         /* thickness 2px */
    background-repeat: no-repeat;
    background-position: 
      left bottom, left bottom 4px, left bottom 8px;   /* gutter 2px */ 
    background-image:
      linear-gradient(to right, blue, blue),           /* bottom line */
      linear-gradient(to right, green, green),         /* middle line */
      linear-gradient(to right, red, red);             /* top line */
  }
  
h1.red{
    background-image:
      linear-gradient(to right, blue, blue), 
      linear-gradient(to right, green, green);     
}
h1.blue{
    background-image:
      linear-gradient(to right, green, green),      
      linear-gradient(to right, red, red);      
}
h1.green{
    background-image:
      linear-gradient(to right, blue, blue), 
      linear-gradient(to right, red, red);      
}
<h1>Hello there</h1>

<h1 class="green">Hello there</h1>

<h1 class="red">Hello there</h1>

<h1 class="blue">Hello there</h1>
like image 37
Asons Avatar answered Oct 27 '22 20:10

Asons


You can actually do this with only 1 pseudo-element.

Here's what I've done (with comments on how to control spacings):

h1 {
    display: inline-block;
    /* controls the last line */
    border-bottom: 2px solid #a3514f;
}

h1:after {
    content: "";
    display: block;
    /* controls space between 1st and 2nd line */
    height: 2px;
    width: 100%;
    /* controls space between 2nd and 3rd line */
    margin-bottom: 2px;
    border-bottom: 2px solid #2762be;
    border-top: 2px solid #e8353b;
}
<h1>Hello there</h1>

This was written based on @APAD1's answer, taking his idea of using borders.

This method offers the advantage of the whole ::after being part of the content of the <h1>, instead of being outside.

like image 26
Ismael Miguel Avatar answered Oct 27 '22 20:10

Ismael Miguel