Textfarbe basierend auf Hintergrundfarbe automatisch in CSS umkehren

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Am Wochenende fiel mir ein interessantes Design für eine Fortschrittsanzeige in einem Videospiel auf. Der %-Fortschritt wurde als Text in der Mitte des Balkens angezeigt und bewegte sich nicht. Aber der Text hatte die gleiche Farbe wie der Hintergrund des Balkens, der von links nach rechts gefüllt wurde. Es sah so aus, als würde der Hintergrund den Text unsichtbar machen, sobald sie sich überlappten, aber stattdessen kehrte sich die Textfarbe in Weiß um, überall dort, wo sie sich mit dem Hintergrund überlappte.

Mein erster Gedanke war: Wie können wir dieses Designmuster nachbilden und was können wir dabei lernen?

Hier ist, was ich mir ausgedacht habe, aber stellen Sie sicher, dass Sie diese Demo auf der neuesten Version von Chrome überprüfen, um alles richtig funktionieren zu sehen

Siehe den Pen Ein reiner CSS-Ladebalken von Robin Rendle (@robinrendle) auf CodePen.

Ziemlich cool, oder? Dies ist mit der erstaunlichen Magie von mix-blend-mode in CSS möglich.

Schauen wir uns zuerst den Markup an

<div class="wrapper">
  <div class="bg">
    <div class="text"></div>
  </div>
</div>

Der .wrapper hält unsere Elemente an Ort und Stelle, .bg wird unser Ladebalken sein, der sich mit der Zeit erhöht, und unser .text-Element wird als Prozentinformation verwendet.

Machen wir das Ganze nur mit CSS

Ein „echter“ Lader im Web würde wahrscheinlich von JavaScript angetrieben und irgendwie auf tatsächliche Daten reagieren. Aber während wir hier Spaß haben, lassen wir das Ganze, sogar das Zählen, nur in CSS passieren (SCSS für die Schleifenunterstützung).

Wir richten unsere Variablen ein und stylen das .bg-Element

$loadingTime: 10s;
$color: rgb(255, 0, 0);

.bg {
  background-color: $color;
  animation: loading $loadingTime linear infinite;
}

Mit der loading-Animation ändern wir die Breite des Elements, wie folgt

@keyframes loading {
  0% {
    width: 0;
  } 100% {
    width: 100%;
  }
}

Vielleicht hätten wir den Überlauf verstecken und die Hintergrundbox mit der transform-Eigenschaft verschieben können (aus Performance-Gründen), aber in dieser kleinen Demo denke ich, dass es in Ordnung ist, die animation der width-Eigenschaft allein zu verwenden.

Um den Inhalt des .text-Elements mit dem korrekten Prozentwert zu aktualisieren, müssen wir ein wenig schlau sein und eine Mischung aus Pseudo-Elementen und Animationen verwenden. Zuerst lassen wir das <div> leer und setzen den content seines after Pseudo-Elements auf 0%, bevor wir eine Animation definieren

.text {
  color: $color;
  width: 200px;
  border: 1px solid $color;

  &:after {
    padding-left: 20px;
    content: "0%";
    display: block;
    text-align: center;
    animation: percentage $loadingTime linear infinite;
  }
}

Was wir also mit der percentage-Animation oben machen wollen, ist, unseren content-Eigenschaft mit jedem Wert von 1 bis 100 zu aktualisieren, wie hier

@keyframes percentage {
  0% {
    content: "0%";
  }
  1% {
    content: "1%"; 
  }
  /* ... */
  100% {
    content: "100%";
  }
}

Aber anstatt all diese @keyframe-Selektoren von Hand zu erstellen, können wir uns mit der @for-Schleifensyntax in Sass vertraut machen

@keyframes percentage { 
  @for $i from 1 through 100 {
    $value: $i + "%";
    #{$value} {
      content: $value;
    }
  }
}

Wenn das ein wenig beängstigend aussieht, keine Sorge! In der dritten Zeile fügen wir die aktuelle Zahl in der Schleife (die wir $i nennen) hinzu, machen sie zu einem String, indem wir % anhängen und sie einer Variablen zuweisen. Dann können wir Interpolation verwenden, um jeden @keyframe-Selektor den content-Eigenschaft auf den richtigen Wert aktualisieren zu lassen.

Der Farbwechsel

Schließlich müssen wir nur noch die Farbe und den mix-blend-mode unseres Pseudo-Elements einstellen und schon haben wir einen reinen CSS-Loader, bei dem die Hintergrundfarbe die Vordergrundfarbe beeinflusst

.text:after {
    /* This value is the OPPOSITE color of our background */
    color: rgb(0, 255, 255); 
    mix-blend-mode: difference;
}

Siehe den Pen Ein reiner CSS-Ladebalken von Robin Rendle (@robinrendle) auf CodePen.

Mit dem difference-Blend-Modus müssen wir den Farbwert des Textelements auf das Gegenteil des Hintergrunds setzen. Wenn unser Hintergrund also rgb(0, 0, 0) ist, müssen wir das Text-Pseudo-Element auf rgb(255, 255, 255) setzen.

Ich denke, diese kleine Demo hilft uns zu erkennen, wie nützlich die mix-blend-mode-Eigenschaft sein kann. Es wird in Zukunft alle möglichen Fälle geben, in denen Schnittstellen Informationen auf Arten offenlegen können, die wir nie für möglich gehalten hätten.

Textfarbe komplett ändern

Das Coole an dieser Technik ist, dass ein Teil des Textes eine Farbe und andere Teile des Textes eine andere Farbe haben. Die Umkehrung geschieht nur basierend darauf, was abgedeckt ist und was nicht, selbst wenn es nur ein Teil eines Buchstabens ist.

Wenn Sie eher eine auf Barrierefreiheit basierende „Ändere die Textfarbe, um sicherzustellen, dass sie genügend Kontrast hat“-Lösung suchen, kann Sass auch dabei helfen.

Ein weiteres Beispiel

Die XOXO-Website verwendete mix-blend-mode: darken; ziemlich oft, um Hintergründe, Formen und Text auf subtile/interessante/schöne Weise interagieren zu lassen, die wir im Web noch nicht oft gesehen haben.

Browser-Unterstützung

Die mix-blend-mode-Eigenschaft wird derzeit nicht gut unterstützt, ebenso wenig wie die animierbare content-Eigenschaft. Stellen Sie also sicher, dass Sie Fallbacks bereitstellen, wenn Sie sich für einen dieser Tricks entscheiden.