Get filter to NOT apply to nested pseudo elements

85 Views Asked by At

I've been implementing email-style color coding for the borders of deeply nested quotes:

deeply nested color-coded 'borders'

Technically, they're not borders per se but :before pseudo elements. And the 'footers' (the bits saying 'dennis on...') reside in :after:

blockquote {
  color: #424242;
  padding-left: 1rem;
  margin-left: 2px;
  position: relative;
}

/* This is how Stack Overflow does rounded corners
   for the left border, along with the relative
   positioning of the blockquote proper. */
blockquote:before {
  background: chocolate;
  border-radius: 8px;
  top: 0;
  left: 0;
  bottom: 0;
  content: "";
  position: absolute;
  width: 3px;
}

/* 'Footer' with source information */
blockquote:after {
  content: '— ' attr(data-source) ' on ' attr(data-date);
  color: #007bff;
  font-style: italic;
  font-size: small;
}

The colors rotate programmatically, per this answer:

blockquote blockquote {
  filter: hue-rotate(307deg) saturate(2.5);
}

Here's the problem: I only intend for the rotation to apply to the 'borders' on the left, not the 'footers'. The 'footers' should render with their assigned color (#007bff, ie blue).

I have tried unsetting the filter on the :after:

blockquote:after {
  filter: none;
}

But this approach won't percolate to the deeply nested :afters. I've tried setting !important as well.

The 'best' I have come up with so far is resetting the rotation and saturation:

blockquote:after {
  filter: hue-rotate(0deg) saturate(0);
}

This does percolate (no clue why), but it results in the 'footers' being gray, which is better, but not the desired result. Again, I need the 'footers' to all be blue like the bottom-most one.

How to achieve this? Since the quoted text itself ('foo', 'bar', etc) isn't color coded, something is working right – I need to apply that to the footers as well.

EDIT: As requested, here's the HTML as well:

<blockquote data-source="dennis" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-425">
  <blockquote data-source="peter" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-424">
    <blockquote data-source="dennis" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-423">
      <p>foo</p>
    </blockquote>
    <p>bar</p>
  </blockquote>
  <p>baz</p>
</blockquote>
1

There are 1 best solutions below

6
Temani Afif On

I will suppose that you have a max number of nesting and you can manually define each case.

I am using the trick from here: https://css-tip.com/hue-manipulation-color-mix/ then I manually calculate the hue angle each time.

blockquote {
  color: #424242;
  padding-left: 1rem;
  margin-left: 2px;
  position: relative;
  --color: chocolate; /* main color */
  /* the color after hue manipulation */
  --new-color: 
    color-mix(in hsl longer hue, 
      var(--color), var(--color) calc(var(--h)*1%/3.6)
  );
}

blockquote:before {
  background: var(--new-color);
  border-radius: 8px;
  top: 0;
  left: 0;
  bottom: 0;
  content: "";
  position: absolute;
  width: 3px;
  filter:  saturate(2.5);
}

/* 'Footer' with source information */
blockquote:after {
  content: '— ' attr(data-source) ' on ' attr(data-date);
  color: #007bff;
  font-style: italic;
  font-size: small;
}

blockquote  {
  --h: 0; 
}
blockquote > blockquote {
  --h: 307; 
}
blockquote > blockquote {
  --h: 254; 
}
blockquote > blockquote > blockquote {
  --h: 201; 
}
blockquote > blockquote > blockquote > blockquote {
  --h: 148; 
}
blockquote > blockquote > blockquote > blockquote > blockquote {
  --h: 95; 
}
<blockquote data-source="dennis" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-425">
  <blockquote data-source="peter" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-424">
    <blockquote data-source="dennis" data-date="Aug 22, 2023 12:07 pm PDT" data-link="#message-423">
      <p>foo</p>
    </blockquote>
    <p>bar</p>
  </blockquote>
  <p>baz</p>
</blockquote>