CSS 混合混合模式/只有白色或黑色

CSS mix blend mode / only white or black

您好,我目前正在尝试找到一种解决方案,如果背景是白色或黑色,则粘性文本在任何其他情况下都变黑。在我的研究过程中,我发现了 mix 混合模式 属性 但制作我想要的东西似乎非常复杂。

.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 20px;
  color:white;
  font-size:60px;
  mix-blend-mode: difference;
}
.panel {
  height: 80vh;
  widht: 100%;
}

.bg-black {
  background: black;
}

.bg-red {
  background: red;
}

.bg-blue {
  background: blue;
}

.bg-green {
  background: green;
}
<div class="sticky">
  My text
</div>
<div>
  <section class="panel"></section>
  <section class="panel bg-black"></section>
  <section class="panel bg-red"></section>
  <section class="panel bg-blue"></section>
  <section class="panel bg-green"></section>
</div>

有人知道可以帮助我的技巧或软件包吗?

非常感谢

我不确定 mix-blend-mode 是否可行,但 filterbackground-clip: text 可以做你想做的事情:

// can ignore this, it's just making the sliders work as R G B
function updateColor() {
  const r = document.getElementById('r').value;
  const g = document.getElementById('g').value;
  const b = document.getElementById('b').value;
  
  document.querySelector('.container').style.background = `rgb(${r},${g},${b}`;
}
.container {
  background: white;
}

.contrast-text {
  font-size: 50vmin;

  background: inherit;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: 
    sepia(5)      /* add some color to grey so the rest works */
    saturate(100) /* increase strength of color channels */
    invert(1)     /* invert the color */
    grayscale(1)  /* make it grey */
    contrast(9);  /* make it black/white */
}
<input type="range" onchange="updateColor()" min=0 max=255 value=255 id="r">
<input type="range" onchange="updateColor()" min=0 max=255 value=255 id="g">
<input type="range" onchange="updateColor()" min=0 max=255 value=255 id="b">

<div class="container">
  <div class="contrast-text"> Text </div>
</div>

我终于找到了很棒的东西!它不如 mix-blend-mode 漂亮,但它完成了工作。

我希望保持 100% css 因为它需要使用 ScrollMagic

const controller = new ScrollMagic.Controller();
const sections = document.querySelectorAll('section');
const menu = document.querySelector('.my-text');


sections.forEach((section, index, arr) => {
  const trigger = '#' + section.id;
  const backgroundColor = window.getComputedStyle(section, null).getPropertyValue('background-color');
 
  const textColor = getContrastYIQ(backgroundColor);

  let previousBackgroundColor = backgroundColor;
  let previousTextColor = getContrastYIQ(previousBackgroundColor);
  

  if (index >= 1) {
    previousBackgroundColor = window.getComputedStyle(arr[index - 1], null).getPropertyValue('background-color');
    previousTextColor = getContrastYIQ(previousBackgroundColor);
  }

  new ScrollMagic.Scene({
      triggerElement: trigger,
      triggerHook: "onLeave",
      offset: -50,
      reverse: true
    })
    .on("enter", function() {
      menu.classList.remove(previousTextColor);
      menu.classList.add(textColor);

    })
    .on("leave", function() {
      menu.classList.remove(textColor);       menu.classList.add(previousTextColor);

    })
    .addTo(controller);
})

// Color contrast helper function
// https://en.wikipedia.org/wiki/YIQ
function getContrastYIQ(rgb) {
  rgb = rgb.substring(4, rgb.length - 1)
    .replace(/ /g, '')
    .split(',');
  const yiq = ((rgb[0] * 299) + (rgb[1] * 587) + (rgb[2] * 114)) / 1000;
  return (yiq >= 128) ? 'black' : 'white';
}
section {
  min-height: 80vh;
}

.my-text {
  position: sticky;
  top: 5vh;
  color: white;
}

.black {
    color: black;
    &:before {
      background: black;
      box-shadow: 0 0.4em 0 0 black, 0 0.80em 0 0 black;
    }
 }

#s1 {
  background-color: black;
}

#s2 {
  background-color:  white;
}

#s3 {
  background-color: #111;
}

#s4 {
  background-color: #9f3;
}

#s5 {
  background-color: #145;
}

#s6 {
  background-color: #f5f; 
}
<script ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/ScrollMagic.min.js"></script>
<div class="my-text">
  MY TEXT</div>
<section id="s1">
</section>
<section id="s2"></section>
<section id="s3"></section>
<section id="s4"></section>
<section id="s5"></section>
<section id="s6"></section>

可以仅使用 CSS 来实现,方法是不对粘性元素应用混合模式,而是对背景(::之前,::之后)项目应用混合模式。

.bg-field::before, .bg-field::after {
  background-color: white;
  mix-blend-mode: difference;
  pointer-events: none;
  content: "";
  position: absolute;
  bottom: 0;
  top: 0;
  right: 0;
  left: 0;
}

.bg-field::before {
  z-index: 1;
}

.bg-field::after {
  background-color: red;
  z-index: -1;
}

bg 字段内的所有内容(如果是固定元素,甚至在外面)都将被着色

我制作了一个代码片段来展示它是如何工作的:https://codepen.io/AndrewKnife/pen/XWzBpeN