Heim > Web-Frontend > CSS-Tutorial > Hauptteil

getComputedStyle: Die guten, die schlechten und die hässlichen Teile

WBOY
Freigeben: 2024-07-28 10:42:23
Original
615 Leute haben es durchsucht

getComputedStyle ist einzigartig. Es führt einige interessante Dinge im Hintergrund aus und verfügt über eine ganz eigene Verwendungsweise. In diesem Beitrag teile ich meine Erfahrungen und Gedanken zu dieser bittersüßen API.

Ich erwarte, dass ich diesen Beitrag bearbeite, da ich heutzutage viel mit dieser Funktion interagiere. Ich denke auch, dass es dafür auch viele Nischenfälle geben kann. Übrigens werde ich am Ende des Beitrags einige Links einfügen, die mir auf meiner Reise geholfen haben.

Was ist getComputedStyle?

Direkt von MDN:

Die Methode Window.getComputedStyle() gibt ein Objekt zurück, das die Werte aller CSS-Eigenschaften eines Elements enthält, nachdem aktive Stylesheets angewendet und alle grundlegenden Berechnungen aufgelöst wurden, die diese Werte möglicherweise enthalten.

Auf einzelne CSS-Eigenschaftswerte wird über vom Objekt bereitgestellte APIs oder durch Indizierung mit CSS-Eigenschaftsnamen zugegriffen.

Verwendungsbeispiel in einfachem JavaScript:

const element = document.getElementById("#box");

// Get the computed styles of an element
const styles = getComputedStyle(element);
Nach dem Login kopieren

Einfach ausgedrückt gibt es Stile für das angegebene Element zurück. Interessant ist hier das Auflösen von Berechnungen. Angenommen, Sie haben in CSS mit calc():
die Eigenschaft width angegeben

#box {
  width: calc(100px - 80px);
}
Nach dem Login kopieren

Als Ergebnis erhalten Sie 20px. Das bedeutet, dass Sie tatsächlich über JavaScript auf Ergebnisse von CSS-Berechnungen zugreifen können. Es berechnet sogar Ansichtsfenster- und Prozenteinheiten (100 vh, 50 % usw.) und gibt das Ergebnis in Pixeln aus. Großartig!

GOTCHA: Der berechnete Wert hängt von den Eigenschaften ab und ist nicht statisch. Das heißt, Sie können nicht erwarten, dass es so etwas berechnet:

#box {
  --box-width: calc(100px - 80px);
  width: var(--box-width);
}
Nach dem Login kopieren
// boxWidth variable will be set to string `calc(100px - 80px)`
// Not `20px`
const boxWidth = getComputedStyle(element)["--box-width"];
Nach dem Login kopieren

Das macht absolut Sinn, da es unmöglich wäre, das Ergebnis einer CSS-Variablen statisch zu berechnen. Es hängt von der Umgebung und den Eigentumsaspekten ab (denken Sie zum Beispiel an Prozentsätze).

Sie erhalten jedoch 20 Pixel, wenn Sie versuchen, auf die Breiteneigenschaft zuzugreifen. Am Ende würde die Breite für das spezifische Element berechnet:

// 20px
const { width } = getComputedStyle(element);
Nach dem Login kopieren

Das ist cool und alles andere als was sind die tatsächlichen Anwendungsfälle?

Übergang eines Elements von 0px zu auto

Wenn Sie diesen Beitrag lesen, nachdem calc-size() in modernen Browsern weit verbreitet ist, hören Sie auf, ihn zu verwenden. Es wird wahrscheinlich unsere Lösung hier übertreffen. Wenn Sie in einer Realität feststecken, in der wir nicht auf das Auto umsteigen können, machen Sie weiter!

Auf Ihrer Reise in die Webentwicklung sind Sie vielleicht schon ein paar Mal auf die Animation von/zu Auto gestoßen. Eine Animationsbibliothek könnte hier gut passen, aber was ist, wenn ich Ihnen sage, dass überhaupt kein Bedarf dafür besteht?

Nehmen wir an, es gibt ein Feld, das wir ein-/ausschalten können und das Textinhalt enthält. Der Textinhalt wird dynamisch sein, daher können wir ihm nicht im Voraus eine maximale Höhe zuweisen. Oh, der Designer möchte dort auch eine Animation, sie muss langsam von 0 Pixel auf die automatische Höhe übergehen.

Das Folgende wird unser HTML und CSS sein:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <style>
    #box {
      position: relative;
      display: block;
      width: fit-content;
      height: 0px;
      overflow: hidden;
      background-color: rebeccapurple;
      color: whitesmoke;
      transition: 1s;
    }
  </style>
  <body>
    <button type="button" id="toggle">toggle</button>
    <div id="box"></div>

    <script type="module" src="/src/main.ts" defer></script>
  </body>
</html>
Nach dem Login kopieren

Auf der Skriptseite werden wir zunächst nicht viel tun. Wir müssen lediglich einen einfachen Zustand beibehalten, um den Textinhalt einzufügen oder zu entfernen. (Ob Sie TS verwenden oder nicht, bleibt Ihnen überlassen):

// get the wrapper div
const box = document.getElementById("box") as HTMLDivElement;
// get the trigger button
const button = document.getElementById("toggle") as HTMLButtonElement;
// state that keeps track
let toggle = false;

function changeBoxContent() {
  if (toggle) {
    box.innerText = `Lorem ipsum dolor sit, 
    amet consectetur adipisicing elit.
    Minima culpa ipsum quibusdam quia
    dolorum excepturi sequi non optio,
    ad eaque? Temporibus natus eveniet
    provident sit cum harum,
    praesentium et esse?`;
  } else {
    box.innerText = "";
  }
}

button.addEventListener("click", () => {
  // flip the toggle
  toggle = !toggle;
  // update the content
  changeBoxContent();

  // ...
});
Nach dem Login kopieren

Der Code hier setzt einfach den inneren Text der Box auf eine Pseudozeichenfolge oder setzt ihn wieder in eine leere Zeichenfolge zurück.

Wenn Sie jetzt auf die Schaltfläche klicken, werden Sie feststellen, dass sich nichts geändert hat. Das liegt daran, dass wir die Höhe der Box auf 0 Pixel setzen und den Überlauf ausblenden.

Um zu wissen, wie viel Platz wir für den Text benötigen, können wir die Höhe der Box auf „Auto“ setzen und getComputedStyle für unsere Box aufrufen. Die Idee hier ist, das Element automatisch so weit vergrößern zu lassen, wie es benötigt, und getComputedStyle hier ruft uns diese Größe in Pixel ab.

button.addEventListener("click", () => {
  // flip the toggle
  toggle = !toggle;
  // update the content
  changeBoxContent();

  // set the element's height to `auto`, this enlarges the element to fit it's content
  box.style.height = "auto";

  // we got our desired height property!
  const height = getComputedStyle(box).height;

  console.log(height);
});
Nach dem Login kopieren

Wenn Sie auf die Schaltfläche klicken, sollten Sie sehen, dass das Feld die erforderliche Höhe hat. Wir können die Höhe auch in Pixeln in der Konsole sehen:

Result A1

Das ist cool, aber wir werden mit Sicherheit nicht umstellen.

Da wir die Höhe kennen, die wir benötigen, können wir die Höhe der Box vielleicht wieder auf den ursprünglichen Wert zurücksetzen. Innerhalb eines Aufrufs von requestAnimationFrame können wir es auf die Höhe setzen, die wir von getComputedStyle erhalten haben. Probieren wir es aus!

button.addEventListener("click", () => {
  // flip the toggle
  toggle = !toggle;
  // update the content
  changeBoxContent();

  // set the element's height to `auto`, this enlarges the element to fit it's content
  box.style.height = "auto";

  // we got our desired height property!
  const height = getComputedStyle(box).height;

  // set the height back to where it was (0px)
  box.style.height = "";

  // set the final height in next animation frame
  requestAnimationFrame(() => {
    box.style.height = height;
  });
});
Nach dem Login kopieren

Da wir wissen, dass wir die Höhe auf 0 Pixel setzen und sie im nächsten Animationsframe ändern, sollten wir eine Animation sehen, oder?

Naja, nicht ganz. Wenn Sie dies in Chrome auf einem High-End-PC ausführen, sollten Sie die Übergangsanimation beobachten, ABER auf Low-End-PCs oder in einigen Browsern (wie Firefox) können Sie sehen, dass sich nichts geändert hat.

Vergleich von Firefox und Chrome auf meinem Computer:

getComputedStyle: The good, the bad and the ugly parts

Der Grund dafür ist, dass die Berechnung des Layouts nach den Stilen erfolgt. Wir können nicht garantieren, dass unsere Layoutberechnung vor der Stilberechnung erfolgt. Anscheinend haben auch Browser unterschiedliche Implementierungen von requestAnimationFrame. (Mehr darüber erfahren Sie hier)

Don't get into despair though! We have multiple solutions for this. We can:

  • Force the browser to run layout calculations immediately before styles
  • Use intertwined requestAnimationFrames to make sure the animation will be run on the next tick (also known as double rAF())

Let's try forcing the browser to calculate styles first. Remember getComputedStyle? I'm sure you do. It'll come to our rescue here too!

Right after we set height back to 0px, we'll force to recalculate the layout:

button.addEventListener("click", () => {
  // flip the toggle
  toggle = !toggle;
  // update the content
  changeBoxContent();

  // set the element's height to `auto`, this enlarges the element to fit it's content
  box.style.height = "auto";

  // we got our desired height property!
  const height = getComputedStyle(box).height;

  // set the height back to where it was (reset)
  box.style.height = "";

  // we're synchronously forcing the browser to recalculate the height of the element
  getComputedStyle(box).height;

  // set the final height in next animation frame
  requestAnimationFrame(() => {
    box.style.height = height;
  });
});
Nach dem Login kopieren

GOTCHA: You might be thinking why we're accessing height property but not assigning it to anything. Well that's because getComputedStyle computes a property on access. It's actually to make it more optimized, it'll only run layout calculations on access to top, left, bottom, right, width and height. Its not documented but good to keep in mind. Try changing it to getComputedStyle(box), you'll see nothing has changed.

So that was one way to solve it and honestly I like this way much better. It's good to know double rAF() trick too, though.

For that we simply need to wrap our requestAnimationFrame with another requestAnimationFrame:

button.addEventListener("click", () => {
  // flip the toggle
  toggle = !toggle;
  // update the content
  changeBoxContent();

  // set the element's height to `auto`, this enlarges the element to fit it's content
  box.style.height = "auto";

  // we got our desired height property!
  const height = getComputedStyle(box).height;

  // set the height back to where it was (reset)
  box.style.height = "";

  // set the final height in next animation frame
  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      box.style.height = height;
    });
  });
});
Nach dem Login kopieren

Think of it like in the next frame, we've queued an animation that'll run on the next frame. I know it sounds weird but that used to solve lots of problems since it has a bug in Chrome too.

That's the wrap! As you can see in a modern world where we have WAAPI, transitions and getComputedStyle still have their use! It's a bit nasty to understand at start but it has it's own way of doing things, what can I say!

Sources:
Transition to Height Auto With Vue.js by Markus Oberlehner
Need cheap paint? Use getComputedStyle().opacity by Webventures

Das obige ist der detaillierte Inhalt vongetComputedStyle: Die guten, die schlechten und die hässlichen Teile. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!