cssmix-blend-mode

Need something like mix-blend-mode to invert matching text color when intersecting bg color is the same


I wonder if anyone can help me. I’ve created a Mondrian style layout using CSS Grid. I have a heading that has been rotated to be vertical that spans a couple of rows and is sticky. I’d like to achieve an effect that when a horizontal black line passes over/under the black heading text the text that intersects the line is white.

Screenshot of Mondrian style grid layout

I think I need to use mix-blend-mode. But so far I’ve not had any luck with my experiments. I’m wondering if I need to fake the horizontal line with a linear-gradient as the background to make it more image like, though I’ve failed on that count too! I’ve added a jsfiddle below for more clarity:

Any help would be much appreciated. Thanks.

I've checked this answer out Change color of text when scrolling over/under another element?, but it's slightly different as it's using different colors in the blend mode.

* {
  box-sizing: border-box;
  margin: 0;
}

html,
body {
  font-family: sans-serif;
  margin: 0;
  padding: 0;
  font-size: 16px;
  color: #212121;
  background: #fdfdfd;
}

p {
  max-width: 80ch;
}

.flow > * + * {
  margin-top: 1.5rem;
}

.content {
  font-size: 1.125rem;
}

.content__heading {
  position: sticky;
  padding: 1.5rem;
}
.content__heading h2 {
  position: sticky;
  top: 1.5rem;
  font-size: clamp(4.5rem, 20vmin, 7.875rem);
  line-height: 1;
  -ms-writing-mode: tb-lr;
      writing-mode: vertical-lr;
  transform: rotate(180deg);
  text-align: right;
  /**
   * I'm trying to get the stuck text to be white anywhere
   * the horizontal black line (grid-row: 4) crosses it.
   */
  mix-blend-mode: difference;
}

.content__subheading {
  font-size: 2.25rem;
}

.content__section {
  padding: 1.5rem;
}

.block {
  width: 100%;
  height: 100%;
}

.block--black {
  background: #212121;
  color: #fdfdfd;
}

.block--white {
  background: #fdfdfd;
  color: #212121;
}

.block--blue {
  background: #4e9af9;
  color: #212121;
}

.block--blue-dark {
  background: #28407d;
  color: #fdfdfd;
}

.block--grey {
  background: #d4d4df;
  color: #212121;
}

.block--yellow {
  background: #e6b500;
  color: #212121;
}

.block--red {
  background: #d2241a;
  color: #212121;
}

.block--1 {
  grid-column: 1/4;
  grid-row: 1;
}

.block--2 {
  grid-column: 7;
  grid-row: 1;
}

.block--3 {
  grid-column: 1;
  grid-row: 3;
}

.block--4 {
  grid-column: 7;
  grid-row: 3;
}

.block--5 {
  grid-column: 1;
  grid-row: 5;
}

.block--6 {
  grid-column: 7;
  grid-row: 5;
}

.block--7 {
  grid-column: 1;
  grid-row: 7;
}

.block--8 {
  grid-column: 3;
  grid-row: 7;
}

.line {
  background: #212121;
  width: 100%;
  height: 100%;
}

.line--v {
  grid-row: 1/-1;
}

.line--v--1 {
  grid-column: 2;
}

.line--v--2 {
  grid-column: 4;
}

.line--v--3 {
  grid-column: 6;
}

.line--h {
  grid-column: 1/-1;
}

.line--h--1 {
  grid-row: 2;
}

.line--h--2 {
  grid-row: 4;
}

.line--h--3 {
  grid-row: 6;
}

.line--h--4 {
  grid-row: 8;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 0.625rem auto 0.625rem minmax(43.75rem, 2fr) 0.625rem 1fr;
  grid-template-rows: 5rem repeat(3, 0.625rem auto);
}

.grid__heading {
  grid-column: 3;
  grid-row: 3/6;
}

.grid__section {
  grid-column: 5;
}

.grid__section--1 {
  grid-row: 3;
}

.grid__section--2 {
  grid-row: 5;
}

.grid__section--3 {
  grid-row: 7;
}
<main class="content">
    <div class="grid">
        <span class="line line--v line--v--1"></span>
        <span class="line line--v line--v--2"></span>
        <span class="line line--v line--v--3"></span>
        
        <div class="block block--grey block--1"></div>
        <div class="block block--black block--2"></div>
        
        <div class="grid__heading content__heading">
            <h2>Hello</h2>
        </div>
        <span class="line line--h line--h--1"></span>
        <section class="grid__section grid__section--1 content__section block block--blue-dark flow">
            <h3 class="content__subheading">Subheading 1</h3>
            <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Iure, soluta eius? Repudiandae nihil doloremque provident debitis laborum beatae laboriosam atque deserunt dicta excepturi, eius dolorem ab ducimus. Quibusdam, odio beatae.</p>
            <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Alias maiores architecto nemo harum quia aperiam, voluptatem error et quaerat dolorum delectus a rem fuga quae sint inventore laboriosam commodi provident?</p>
            <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dicta alias eos, non deleniti necessitatibus similique at tempora animi perferendis provident sit unde accusamus fugiat totam modi nostrum? Unde, neque accusamus.</p>
        </section>
        
        <div class="block block--red block--3"></div>
        <div class="block block--yellow block--4"></div>
        <div class="block block--red block--5"></div>
        <span class="line line--h line--h--2"></span>
        <section class="grid__section grid__section--2 content__section flow">
            <h3 class="content__subheading">Subheading 2</h3>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quos et voluptate obcaecati quasi nobis aliquam, voluptates esse expedita ullam dolores quae rem itaque cupiditate nam recusandae quia ipsam praesentium omnis!</p>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquam natus asperiores delectus tenetur facere id provident nobis! Sit blanditiis debitis, recusandae assumenda laboriosam quis commodi amet, doloribus eveniet molestiae minima.</p>
        </section>
        <div class="block block--grey block--6"></div>
        
        <div class="block block--black block--7"></div>
        <div class="block block--yellow block--8"></div>
        <span class="line line--h line--h--3"></span>
        <section class="grid__section grid__section--3 content__section block--yellow flow">
            <h3 class="content__subheading">Subheading 3</h3>
            <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Facere atque ad vitae nobis asperiores velit eligendi architecto, maiores reprehenderit dolore et pariatur nihil quo, provident, possimus eaque sint dolor placeat!</p>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate natus vero quaerat expedita facere neque repellendus dolor perspiciatis ullam incidunt aliquid amet illo eligendi, totam possimus aspernatur, sequi ipsam voluptatum!</p>
            <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Minima ullam error sint quae! Numquam provident suscipit cum saepe quas vel delectus distinctio, magni, expedita nam sunt perferendis similique laborum eum.</p>
        </section>
        <span class="line line--h line--h--4"></span>
    </div>
</main>


Solution

  • You need to apply mix-blend-mode to the parent element and color: white (on the text) to apply the desired effect. Keep in mind that if you're not using black (#000) or white (#fff) you might not get the colors you started out with due to blending.

    My solution:

    .content__heading {
      position: sticky;
      padding: 1.5rem;
      mix-blend-mode: difference;
    }
    
    .content__heading h2 {
      position: sticky;
      top: 1.5rem;
      font-size: clamp(4.5rem, 20vmin, 7.875rem);
      line-height: 1;
      -ms-writing-mode: tb-lr;
          writing-mode: vertical-lr;
      transform: rotate(180deg);
      text-align: right;
      /* add color white to achieve the right inversion */
      color: white;
    }