MGreenfield
MGreenfield

Reputation: 365

Make Ribbon Appear Behind Rectangle

I am trying to create a ribbon at the beginning of a rectangle. However, I cannot figure out how to make it appear BEHIND the rectangle.

Please see this codepen: http://codepen.io/gosusheep/pen/aOqOBy

The part for creating the ribbon and putting it behind the rectangle is here:

.rectangle::before{
  content: "";
  width: 0;
  height: 0;
  display: block;
  position: absolute;
  z-index: -1;
  border-left: 25px solid transparent;
  border-right: 25px solid $blue;
  border-top: 25px solid $blue;
  border-bottom: 25px solid $blue;
  left: -30px;
  top: 10%;
}

Even with position: absolute, and z-index: -1, it appears ON TOP of the div.

Can anyone help with this?

Upvotes: 4

Views: 212

Answers (3)

Harry
Harry

Reputation: 89760

The reason for your problem is not because children cannot be positioned behind their parent but because you are using a transform on the parent. Using transforms affect the stacking context like mentioned in this answer by BoltClock.

One solution would be to avoid the transform totally and use left: calc(50% - 100px) instead to position the ribbon at the center (like in the below snippet). (50% - 100px) is used as the value because 100px is half of the box width (50% is the center point of the parent).

.rectangle {
  width: 200px;
  height: 50px;
  background-color: #8080ff;
  position: relative;
  left: calc(50% - 100px); /* newly added */
  border: 1px #6666ff solid;
}

ul {
  list-style: none;
}

li {
  display: inline;
}

li + li::before {
  content: " | ";
}

.container {
  width: 100%;
  position: relative;
}

.rectangle {
  width: 200px;
  height: 50px;
  background-color: #8080ff;
  position: relative;
  left: calc(50% - 100px); /* newly added */
  border: 1px #6666ff solid;
}

.rectangle::before {
  content: "";
  width: 0;
  height: 0;
  display: block;
  position: absolute;
  z-index: -1;
  border-left: 25px solid transparent;
  border-right: 25px solid #8080ff;
  border-top: 25px solid #8080ff;
  border-bottom: 25px solid #8080ff;
  left: -30px;
  top: 10%;
}
<p>put a pipe between nav elements</p>
<nav>
  <ul>
    <li>banana</li>
    <li>woof</li>
    <li>quack</li>
  </ul>
</nav>
<p>Ribbon on the end of a rectangle</p>
<div class='container'>
  <div class='rectangle'></div>
</div>


If in case you can't use the above solution, then you could follow the approach described below.

Assuming you don't have any other use for the ::after pseudo-element, you could use that to create the rectangle and give it a z-index higher than the ::before pseudo-element to make it appear behind the rectangle.

/* Modified */

.rectangle {
  width: 200px;
  height: 50px;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

/* Added */

.rectangle::after {
  content: "";
  width: 100%;
  height: 100%;
  top: 0px;
  left: 0px;
  display: block;
  position: absolute;
  background-color: #8080ff;
  border: 1px #6666ff solid;
  z-index: -1;
}

.rectangle{
  padding: 4px;
  box-sizing: border-box;
}

Below is a sample snippet:

ul {
  list-style: none;
}
li {
  display: inline;
}
li + li::before {
  content: " | ";
}
.container {
  width: 100%;
  position: relative;
}
.rectangle::before {
  content: "";
  width: 0;
  height: 0;
  display: block;
  position: absolute;
  z-index: -2;
  border-left: 25px solid transparent;
  border-right: 25px solid #8080ff;
  border-top: 25px solid #8080ff;
  border-bottom: 25px solid #8080ff;
  left: -30px;
  top: 10%;
}

/* Modified */

.rectangle {
  width: 200px;
  height: 50px;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

/* Added */

.rectangle::after {
  content: "";
  width: 100%;
  height: 100%;
  top: 0px;
  left: 0px;
  display: block;
  position: absolute;
  background-color: #8080ff;
  border: 1px #6666ff solid;
  z-index: -1;
}

.rectangle{
  padding: 4px;
  box-sizing: border-box;
}
<p>put a pipe between nav elements</p>
<nav>
  <ul>
    <li>banana</li>
    <li>woof</li>
    <li>quack</li>
  </ul>
</nav>
<p>Ribbon on the end of a rectangle</p>
<div class='container'>
  <div class='rectangle'>
    Some content
  </div>
</div>

Upvotes: 2

lmgonzalves
lmgonzalves

Reputation: 6588

What is happening here is that apparently, the property transform: translateX(-50%); it's "overriding" in some way the z-index. My solution is just center rectangle otherwise, for example:

.rectangle{
    margin: 0 auto;
}

DEMO

Upvotes: 2

jperelli
jperelli

Reputation: 7197

Solution here, look closely at z-indexes and positions

.container{
  position: relative;
  width: 100%;
  z-index: 1;
}

.rectangle{
  width: 200px;
  height: 50px;
  background-color: $blue;
  position: absolute;
  left: 50%;
  border: 1px darken($blue,5%) solid;
}

.rectangle::after{
  content: "";
  width: 0;
  height: 0;
  border-left: 25px solid transparent;
  border-right: 25px solid $blue;
  border-top: 25px solid $blue;
  border-bottom: 25px solid $blue;
  left: -30px;
  top: 10px;
  position: absolute;
  z-index: -1;
}

And your codepen edited http://codepen.io/anon/pen/mJXeed working now

Upvotes: 1

Related Questions