2

I'm trying to create a "cycling rainbow glow" effect for text in CSS. I've more or less accomplished that, but I've ran into something I can't explain. When I remove the superfluous filter: blur(0px) from the parent element the ::after psudo-element collapses to the left.

.rainbow {
    display: inline-block;
    color: white;
    filter: blur(0px);
}

.rainbow::after {
    content: attr(data-text);
    z-index: -1;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: linear-gradient(90deg,
        hsl(0, 100%, 50%),
        hsl(30, 100%, 50%),
        hsl(60, 100%, 50%),
        hsl(90, 100%, 50%),
        hsl(120, 100%, 50%),
        hsl(150, 100%, 50%),
        hsl(180, 100%, 50%),
        hsl(210, 100%, 50%),
        hsl(240, 100%, 50%),
        hsl(270, 100%, 50%),
        hsl(300, 100%, 50%),
        hsl(330, 100%, 50%),
        hsl(360, 100%, 50%))
        0 0 / 200% 100%;
    -webkit-background-clip: text;
    -moz-background-clip: text;        
    -webkit-text-fill-color: transparent;
    -moz-text-fill-color: transparent;
    filter: blur(10px);
    animation: scroll_background 2s linear infinite;
}

@keyframes scroll_background {
  to { background-position: -200% 0 }
}

https://jsfiddle.net/tpm1gf5v/

Chris_F
  • 4,991
  • 5
  • 33
  • 63
  • 2
    https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context – Kaiido Dec 09 '22 at 02:10

1 Answers1

1

It looks like this is because without filter: blur(0px), the rainbow is no longer a relative container (according to this answer), and also does not have a stacking context to place ::after properly.

This may have caused ::after to be placed relative to body which resulted in the error.

It seems to be fixed by giving rainbow a relative positioning, and specify a new stacking context:

.rainbow {
  display: inline-block;
  color: white;

  /*  Add this */
  position: relative;

  /*  Add one of these two for a new stacking context */
  isolation: isolate;
  /* z-index: 0; */
}

Example: (modified from the posted jsfiddle)

html,
body {
  background: #d6daf0;
  font-family: arial, helvetica, sans-serif;
  font-size: 100px;
}

.rainbow {
  display: inline-block;
  color: white;
  
  /*  Add this */
  position: relative;
  
  /*  Add one of these two for a new stacking context */
  isolation: isolate;
  /* z-index: 0; */
}

.rainbow::after {
  content: attr(data-text);
  z-index: -1;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(90deg,
      hsl(0, 100%, 50%),
      hsl(30, 100%, 50%),
      hsl(60, 100%, 50%),
      hsl(90, 100%, 50%),
      hsl(120, 100%, 50%),
      hsl(150, 100%, 50%),
      hsl(180, 100%, 50%),
      hsl(210, 100%, 50%),
      hsl(240, 100%, 50%),
      hsl(270, 100%, 50%),
      hsl(300, 100%, 50%),
      hsl(330, 100%, 50%),
      hsl(360, 100%, 50%)) 0 0 / 200% 100%;
  -webkit-background-clip: text;
  -moz-background-clip: text;
  -webkit-text-fill-color: transparent;
  -moz-text-fill-color: transparent;
  filter: blur(10px);
  animation: scroll_background 2s linear infinite;
}

@keyframes scroll_background {
  to {
    background-position: -200% 0
  }
}
<span class="rainbow" data-text="Hello, World!">Hello, World!</span>

Hope this will help.

John Li
  • 6,976
  • 3
  • 3
  • 27