MDNs Effekt für abgeschnittenen Text neu erstellen

Avatar of Geoff Graham
Geoff Graham am

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

Es ist kein Geheimnis, dass MDN im März ein neues Design eingeführt hat. Es ist großartig! Und es gibt einige süße CSS-Perlen darin, die Spaß machen anzusehen. Eines dieser Juwelen ist, wie Kartenkomponenten abgeschnittenen Text verarbeiten.

Ziemlich cool, oder? Ich möchte das gleich auseinandernehmen, aber ein paar Dinge ziehen mich wirklich zu diesem Ansatz hin.

  • Es ist ein Beispiel für absichtliches Abschneiden von Inhalten. Wir haben dies an anderer Stelle als CSS-Datenverlust bezeichnet. Und obwohl Datenverlust im Allgemeinen eine schlechte Sache ist, gefällt mir, wie er hier eingesetzt wird, da Auszüge als Teaser für den vollständigen Inhalt gedacht sind.
  • Dies unterscheidet sich vom Abschneiden von Text mit text-overflow: ellipsis, einem Thema, das kürzlich aufkam, als Eric Eggert Bedenken dazu äußerte. Das Hauptargument dagegen ist, dass es keine Möglichkeit gibt, den abgeschnittenen Text wiederherzustellen – assistierende Technologien kündigen ihn an, aber sehende Benutzer haben keine Möglichkeit, ihn wiederherzustellen. MDNs Ansatz bietet in diesem Bereich etwas mehr Kontrolle, da die Beschneidung lediglich visuell ist.

Also, wie hat MDN das gemacht? Nichts Besonderes, was das HTML angeht, nur ein Container mit einem Absatz.

<div class="card">
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore consectetur temporibus quae aliquam nobis nam accusantium, minima quam iste magnam autem neque laborum nulla esse cupiditate modi impedit sapiente vero?</p>
</div>

Wir können ein paar Basistyle hinzufügen, um die Dinge zu festigen.

Wieder nichts Besonderes. Unser Ziel ist es, den Inhalt nach zum Beispiel der dritten Zeile abzuschneiden. Wir können dem Absatz eine max-height geben und den Überlauf dafür ausblenden.

.card p {
  max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
  overflow: hidden; /* Cut off the content */
}

Halt halt, was ist mit diesem calc() Kram? Beachten Sie, dass ich oben eine --base Variable eingerichtet habe, die als gemeinsamer Multiplikator verwendet werden kann. Ich verwende sie, um die font-size, line-height, padding für die Karte und jetzt die max-height des Absatzes zu berechnen. Ich finde es einfacher, mit konstanten Werten zu arbeiten, insbesondere wenn die benötigte Größe wirklich auf Skalierung basiert, wie hier. Ich habe bemerkt, dass MDN eine ähnliche --base-line-height Variable verwendet, wahrscheinlich für den gleichen Zweck.

Die dritte Textzeile ausblenden lassen? Das ist ein klassischer linear-gradient() auf dem :after Pseudo-Element des Absatzes, das unten rechts an die Karte angepinnt ist. Also, das können wir so einrichten.

.card p:after {
  content: ""; /* Needed to render the pseudo */
  background-image: linear-gradient(to right, transparent, var(--background) 80%);
  position: absolute;
  inset-inline-end: 0; /* Logical property equivalent to `right: 0` */
}

Beachten Sie, dass ich eine --background Variable aufrufe, die auf denselben Hintergrundfarbwert gesetzt ist, der auch auf dem .card selbst verwendet wird. So scheint der Text in den Hintergrund zu verblassen. Und ich habe festgestellt, dass ich den zweiten Farbstop im Gradienten anpassen musste, da der Text nicht vollständig verborgen ist, wenn der Gradient bis zu 100 % reicht. Ich fand 80% als einen guten Sweet Spot für meine Augen.

Und ja, :after benötigt eine height und width. Die height ist es, wo die --base Variablen wieder ins Spiel kommen, denn wir wollen, dass sie an die line-height des Absatzes angepasst wird, um den Text mit der Höhe von :after abzudecken.

.card p:after {
  /* same as before */
  height: calc(1rem * var(--base) + 1px);
  width: 100%; /* relative to the .card container */
}

Das Hinzufügen eines zusätzlichen Pixels Höhe schien den Trick zu tun, aber MDN konnte es ohne hinbekommen, als ich in DevTools nachgeschaut habe. Aber ich verwende auch top (oder inset-block-start) nicht, um den Gradienten in diese Richtung zu versetzen. 🤷‍♂️

Da p:after absolut positioniert ist, müssen wir dem Absatz explizit eine relative Positionierung erklären, um :after in seinem Fluss zu halten. Andernfalls würde :after vollständig aus dem Dokumentfluss gerissen und außerhalb der Karte landen. Dies wird zum vollständigen CSS für den .card Absatz.

.card p {
  max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
  overflow: hidden; /* Cut off the content */
  position: relative; /* needed for :after */
}

Wir sind fertig, oder? Nein! Der verdammte Gradient scheint einfach nicht an der richtigen Position zu sein.

Ich gebe zu, ich habe mich da vertan und MDN in DevTools aufgerufen, um zu sehen, was ich übersehen hatte. Oh ja, :after muss als Blockelement angezeigt werden. Es ist offensichtlich, wenn man einen roten Rand hinzufügt.🤦‍♂️

.card p:after {
  content: "";
  background: linear-gradient(to right, transparent, var(--background) 80%);
  display: block;
  height: calc(1rem * var(--base) + 1px);
  inset-block-end: 0;
  position: absolute;
  width: 100%;
}

Jetzt alles zusammen!

Und ja, sieht klingt so, als ob VoiceOver den vollständigen Text respektiert. Ich habe jedoch keine anderen Screenreader getestet.

Ich habe auch bemerkt, dass MDNs Implementierung pointer-events von p:after entfernt. Wahrscheinlich eine gute defensive Taktik, um seltsame Verhaltensweisen beim Auswählen von Text zu verhindern. Ich habe es hinzugefügt und das Auswählen von Text fühlt sich ein wenig reibungsloser an, zumindest in Safari, Firefox und Chrome.