1

I was following a guide for making a ribbon with CSS. However, I attempted to modify this by adding a CSS3 Animation to the position, as seen in this JSFiddle.

As you can see, with the animation, the main ribbon element falls behind the :before & :after pseudo-elements, instead of above them as it should (and does without the animation). I've tried explicitly setting the z-index on all elements but it doesn't seem to affect this. Does anyone know why this would be happening, or what I can do to fix it? For the record, I'm viewing through the latest Google Chrome and am not worried about cross-browser compatibility for the moment. Thank you!

Here's the ribbon code:

.ribbon {
    font-size: 16px !important;
    /* This ribbon is based on a 16px font side and a 24px vertical rhythm. I've used em's to position each element for scalability. If you want to use a different font size you may have to play with the position of the ribbon elements */
    width: 50%;
    position: relative;
    background: #ba89b6;
    color: #fff;
    text-align: center;
    padding: 1em 2em;
    /* Adjust to suit */
    margin: 2em auto 3em;
    /* Based on 24px vertical rhythm. 48px bottom margin - normally 24 but the ribbon 'graphics' take up 24px themselves so we double it. */
    /*CODE I ADDED*/
    animation: flyRibbon 30s linear infinite;
    -webkit-animation: flyRibbon 30s linear infinite;
}
.ribbon:before, .ribbon:after {
    content:"";
    position: absolute;
    display: block;
    bottom: -1em;
    border: 1.5em solid #986794;
    z-index: -1;
}
.ribbon:before {
    left: -2em;
    border-right-width: 1.5em;
    border-left-color: transparent;
}
.ribbon:after {
    right: -2em;
    border-left-width: 1.5em;
    border-right-color: transparent;
}
.ribbon .ribbon-content:before, .ribbon .ribbon-content:after {
    content:"";
    position: absolute;
    display: block;
    border-style: solid;
    border-color: #804f7c transparent transparent transparent;
    bottom: -1em;
}
.ribbon .ribbon-content:before {
    left: 0;
    border-width: 1em 0 0 1em;
}
.ribbon .ribbon-content:after {
    right: 0;
    border-width: 1em 1em 0 0;
}

Here's the animation code:

@keyframes flyRibbon {
    100% {
        transform: translateX(200vw);
        -webkit-transform: translateX(200vw);
    }
}
Ruben Martinez Jr.
  • 3,199
  • 5
  • 42
  • 76

2 Answers2

2

Adding a div around the ribbon and applying the animation css to it instead of to the h1 element should fix this.

HTML:

<div class="container">
    <h1 class="ribbon">
       <strong class="ribbon-content">Everybody loves ribbons</strong>
    </h1>
</div>

CSS:

.container {
    animation: flyRibbon 30s linear infinite;
    -webkit-animation: flyRibbon 30s linear infinite;
}

JSFiddle

quw
  • 2,844
  • 1
  • 26
  • 35
  • 1
    It might be related to this [webkit bug](https://bugs.webkit.org/show_bug.cgi?id=61824) regarding z-index with css transforms. [StackOverflow Discussion](http://stackoverflow.com/questions/5472802/css-z-index-lost-after-webkit-transform-translate3d). This is a really weird glitch that you found. – quw Aug 21 '14 at 21:38
2

This is not a bug. This is a specified behavior of z-index for elements that create stacking contexts, and .ribbon creates a stacking context because it has transform (in the animation). With transform, the element becomes the root of the stacking context and no child box can be placed below it.

As a workaround without extra markup, you can give the inner contatiner block display and position it above the ribbon ends, like in this example.

Ilya Streltsyn
  • 13,076
  • 2
  • 37
  • 57