Fokussierung eines `background-image` an einer präzisen Stelle mit Prozentangaben

Avatar of Jay Sitter
Jay Sitter am

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

Nehmen wir an, Sie haben ein Element mit einem background-image, bei dem nur ein Teil des Bildes sichtbar ist, da das Bild größer ist als das Element selbst. Der Rest wird abgeschnitten, außerhalb des Elements.

Nun möchten Sie, dass sich das `background-image` so verschiebt, dass der Mittelpunkt des Elements auf einen bestimmten Punkt darin fokussiert wird. Und das möchten Sie auch *mit Prozentwerten* und nicht mit Pixeln tun. Wir müssen dabei clever vorgehen.

Das wird einige mathematische Berechnungen erfordern.

Verwenden wir dieses Bild als Beispiel, das Markierungen zur Größenbestimmung enthält.

Und hier ist unser Element, auf das das `background-image` angewendet wurde. Beachten Sie, dass wir nur den (oberen) linken Teil des Bildes sehen können.

Siehe den Pen Background Focus: no position von Jay (@jsit) auf CodePen.

Nun nehmen wir an, wir möchten einen bestimmten Punkt im Bild mit der Mitte dieses Elements ausrichten. Sagen wir, der Punkt 300 Pixel vom linken Rand entfernt.

Da wir diese Position in Pixeln abfragen, ist es unkompliziert. Ohne definierte Position beginnt das `background-image` mit dem Punkt bei 100 Pixeln in der Mitte, daher müssen Sie es um 200 Pixel nach links verschieben.

Siehe den Pen Background Focus: pixel position von Jay (@jsit) auf CodePen.

Lassen Sie uns das formalisieren.

Der `x`-Wert, den Sie für `background-position-x` verwenden, wird wie folgt berechnet:

(0.5 × [bounding box width]) - [x-coordinate]
             0.5 × 200px -              300px
                   100px -              300px = -200px

Es dauert einen Moment, bis man es versteht, aber es ist nichts zu anstrengend. Wahrscheinlich hätten Sie das intuitiv herausfinden können, ohne eine Formel verwenden zu müssen.

Aber was ist, wenn Sie `background-position-x` als Prozentsatz ausdrücken möchten (oder müssen)? Sollte nicht allzu schwer sein, oder? Versuchen wir, einen Prozentsatz zu verwenden, um uns wieder bei 300px zu zentrieren. Wir hatten ein `background-position-x` von `-200px`, also wandeln wir das in Prozent um: -200 / 800 = -25%, also:

Siehe den Pen Background Focus: percentage (1st attempt) von Jay (@jsit) auf CodePen.

Hm. Das hat überhaupt nicht funktioniert. Vielleicht müssen wir einen positiven Wert verwenden?

Siehe den Pen Background Focus: percentage (2nd attempt) von Jay (@jsit) auf CodePen.

Das ist besser, aber es ist zentriert bei, wie… 250px? Wie wäre es als Prozentsatz der Breite der Bounding Box: 300 / 200 = 150%. Das kann nicht richtig sein…

Siehe den Pen Background Focus: percentage (3rd attempt) von Jay (@jsit) auf CodePen.

Ja, das stimmt nicht.

Gehen wir zurück. Was passiert, wenn wir das tun?

Siehe den Pen Background Focus: percentage (4th attempt) von Jay (@jsit) auf CodePen.

Das fühlt sich irgendwie richtig an; `background-position-x: 100%;` macht das `background-image` rechtsbündig und zentriert bei 700px, oder 7/8 der Bildbreite. Aber was, wenn wir es bei 100% zentrieren wollten? Ich schätze, wir müssten… 9/8 tun?

Siehe den Pen Background Focus: percentage (5th attempt) von Jay (@jsit) auf CodePen.

Zu diesem Zeitpunkt bin ich nicht überrascht, dass das nicht funktioniert hat.

Das fühlt sich nicht wie der richtige Weg an. Gehen wir zurück.

Was sagt die Spezifikation?

Bei einem Wertpaar von ‚0% 0%‘ wird beispielsweise die obere linke Ecke des Bildes mit der oberen linken Ecke des normalerweise durch den Polsterbereich des Feldes definierten Bereichs ausgerichtet. Ein Wertpaar von ‚100% 100%‘ platziert die untere rechte Ecke des Bildes in der unteren rechten Ecke des Bereichs. **Bei einem Wertpaar von ‚75% 50%‘ wird der Punkt 75 % horizontal und 50 % vertikal auf dem Bild an den Punkt 75 % horizontal und 50 % vertikal auf dem Bereich gelegt.**

Vielleicht können wir das rückentwickeln.

Bei letzterem, 112,5%, wurde der Punkt bei 112,5 % des `background-image` mit dem Punkt bei 112,5 % der Bounding Box ausgerichtet. Das ergibt irgendwie Sinn. Die Spezifikation scheint so geschrieben zu sein, dass sie nur drei Werte einfach macht: 0 %, 50 % und 100 %. Jeder andere Wert ist nicht so intuitiv.

Mit `background-position-x: 0;` waren wir auf 100px oder 12,5 % fokussiert. Mit `background-position-x: 100%;` waren wir auf 700px oder 87,5 % fokussiert. Wie sieht `background-position-x: 50%;` genau aus?

Siehe den Pen Background Focus: percentage (6th attempt) von Jay (@jsit) auf CodePen.

50 % ist hier so etwas wie unser „Anker“; es ist der Punkt, an dem unser gewünschter Fokuspunkt und die entsprechenden `background-position-x`-Werte gleich sind.

Nehmen wir an, wir möchten uns auf 700 px oder 87,5 % konzentrieren. Wir gehen 100 % vom Zentrum weg: 50 % + 50 %.

Siehe den Pen Background Focus: percentage (4th attempt) von Jay (@jsit) auf CodePen.

Bei `background-position-x: 100%;` hat sich die Mitte unserer Bounding Box vom Mittelpunkt des Bildes wegbewegt, 3/4 des Weges zum äußersten rechten Rand (von 400px auf 700px). Wenn wir uns zum äußersten rechten Rand „bewegen“ wollen, brauchen wir noch dieses zusätzliche 1/4 oder 200px. 1/4 ist 1/3 von 3/4, also müssen wir ein Drittel mehr gehen als gerade eben, oder insgesamt 66,667 % vom Zentrum entfernt.

Siehe den Pen Background Focus: percentage (7th attempt) von Jay (@jsit) auf CodePen.

Puh! Um uns auf den äußersten rechten Rand eines `background-image` zu konzentrieren, das viermal so groß ist wie unsere Bounding Box, müssen wir `background-position-x: 116.667%;` setzen.

Wie zum Teufel sollen wir das herausfinden?

Es ist ein *Unterschied* von 16,667 % gegenüber den 100 %, die wir erwarten könnten. Wenn wir uns also auf unser ursprüngliches Ziel von 300 px (oder 37,5 %) konzentrieren wollten, würden wir, äh, 16,667 % hinzufügen? Auf keinen Fall wird das funktionieren.

Siehe den Pen Background Focus: percentage (8th attempt) von Jay (@jsit) auf CodePen.

Nein.

Wenn wir uns auf den äußersten linken Rand konzentrieren wollten, würden wir wahrscheinlich 16,667 % von 0 % abziehen, oder? Das klingt richtig.

Siehe den Pen Background Focus: percentage (9th attempt) von Jay (@jsit) auf CodePen.

Cool!

Um sich bei 100 % oder 0 % zu konzentrieren, müssen Sie diese Werte „überschreiten“, wenn sie vom Zentrum aus gemessen werden.

Wenn wir uns also auf 0 % konzentrieren wollen, oder „100 % nach links vom Zentrum“, müssen wir 66,667 % von 50 % abziehen. Wenn wir uns auf 100 % konzentrieren wollen, oder „100 % nach rechts vom Zentrum“, müssen wir 66,667 % zu 50 % hinzufügen.

Ich hätte erwartet, 50 % zu 50 % hinzufügen oder abziehen zu müssen, um zu diesen Rändern zu gelangen: ein Verhältnis von 1:1 von „wie weit ich vom Zentrum weg will“ zu „was mein `background-position-x`-Wert sein soll“. Stattdessen müssen wir ein Verhältnis von 4:3 verwenden. Mit anderen Worten, wir müssen einen Wert verwenden, der um vier Drittel „vom Zentrum weg“ liegt.

Die Dinge werden hier etwas unübersichtlich, also führen wir einige Begriffe ein.

  • c: Gewünschter Fokuspunkt (in Prozent) vom linken Rand des Hintergrundbildes
  • z: Zoomfaktor (Breite des Hintergrundbildes ÷ Breite der Bounding Box)
  • p: `background-position-x`, um sich auf c zu konzentrieren, gegeben z

Wir nehmen also die Entfernung eines Fokuspunktes vom Zentrum (c − 50), multiplizieren sie mit 4/3 und addieren dieses Ergebnis zu „dem Zentrum“, oder 50.

Wenn Sie sich auf den Punkt bei 600px (oder 75 %) konzentrieren möchten, sollte mein `background-position-x`-Wert sein:

(75% − 50%) × 4/3 + 50% = 83.333%

Ja, das klingt, als könnte es funktionieren! Bitte, bitte, bitte.

Siehe den Pen Background Focus: percentage (10th attempt) von Jay (@jsit) auf CodePen.

Fantastisch!

Und wenn Sie sich auf 200px oder 25 % konzentrieren möchten, würden Sie Folgendes tun:

(25% − 50%) × 4/3 + 50% = 16.667%

Siehe den Pen Background Focus: percentage (11th attempt) von Jay (@jsit) auf CodePen.

Wow.

Lassen Sie uns dies verallgemeinern.

(c − 50%) × 4/3 + 50% = p

Warum also 4/3? 4 ist das Verhältnis der Breite unseres `background-image` zur Breite unserer Bounding Box; und 3 ist… 1 weniger als 4. Könnte es so einfach sein? Versuchen wir ein größeres `background-image`, diesmal 1000 Pixel breit, also 5-mal so breit wie unsere Bounding Box. Und versuchen wir erneut, uns auf den Punkt bei 200 px zu konzentrieren. Hier wäre unsere Gleichung:

(20% − 50%) × 5/4 + 50% = 12.5%

Siehe den Pen Background Focus: percentage (12th attempt) von Jay (@jsit) auf CodePen.

Oh mein Gott. Es funktioniert!

Um also zu unserer Gleichung zurückzukehren, mit einem variablen Verhältnis von Hintergrund zu Bounding Box:

(c − 50%) × z/(z − 1) + 50% = p

Lassen Sie uns das in englische Worte fassen.

Gegeben ein Punkt auf einem `background-image` an der Position c…

  1. wobei c als Prozentsatz der Breite des Bildes ausgedrückt wird.
  2. wobei c im horizontalen Zentrum der Bounding Box des Hintergrundbildes liegen soll.
  3. und wobei das `background-image` z-mal so breit ist wie seine Bounding Box.

ist das korrekte `background-position-x` p (ausgedrückt als Prozentsatz) gegeben durch die folgende Formel:

(c − 50%) × z/(z − 1) + 50% = p

Können wir das noch weiter verallgemeinern?

Was wäre, wenn wir den Punkt bei 25 % des `background-image` mit dem Punkt bei 75 % der Bounding Box ausrichten wollten? Juchu!

Kehren wir zu unserer ursprünglichen Formel zurück.

(c − 50%) × z/(z − 1) + 50% = p

Führen wir nun einige neue Begriffe ein.

  • b: Gewünschter Fokuspunkt (in Prozent) vom linken Rand der Bounding Box. Zuvor hatten wir angenommen, dass dieser immer 50 % ist, damit die Mitte der Bounding Box auf unser Ziel im `background-image` fokussiert wird.
  • d: Fokuspunkt des `background-image` (in Prozent), der auf die Mitte der Bounding Box ausgerichtet werden soll, um c auf b in der Bounding Box auszurichten; wenn d des `background-image` mit 50 % der Bounding Box ausgerichtet ist, dann wird c des `background-image` mit b der Bounding Box ausgerichtet.

Denken wir es so.

Die Position c eines `background-image` mit der Position b einer Bounding Box auszurichten, bedeutet, eine andere Position, d, eines `background-image` mit der Mitte der Bounding Box auszurichten – und das wissen wir bereits. Können wir also einen Weg finden, d, den Punkt, den wir bei 50 % benötigen, aus c, b und z abzuleiten? Sicher!

Mit unserem 800 Pixel breiten `background-image` in einer 200 Pixel breiten Bounding Box (z = 4), wenn wir den rechten Rand der Bounding Box (b = 100 %) auf die Position bei 600 Pixeln (c = 75 %) im Bild fokussieren wollen, möchten wir, dass die Mitte der Bounding Box auf den Punkt bei 500 Pixeln (d = 62,5 %) fokussiert wird.

Wie kommen wir von c (75 %) auf d (62,5 %)? Woher kommt dieser Unterschied von -12,5 %?

Nun, unser b war 100 %, 50 % mehr als unser altes „Standard“-b von 50 %. Und 12,5 % ist 1/4 davon; 1/4 ist das Inverse unseres z von 4. Kommt daher unser d? Das wäre:

d = c + (50% - b)/z

Sieht vielversprechend aus. Nun können wir d für c in der ursprünglichen Formel einsetzen.

(d − 50%) × z/(z − 1) + 50% = p

Oder

(c + (50% − b)/z - 50%) × z/(z − 1) + 50% = p

Puh! Testen wir das. Versuchen wir, die Position bei 25 % in unserem `background-image` (200 px) mit der Position bei 75 % in unserer Bounding Box auszurichten. Das wäre:

p = (25% + (50% - 75%)/4 - 50%) × 4/(4 - 1) + 50%
p = -31.25% × 1.333 + 50%
p = 8.333%

Siehe den Pen Background Focus: percentage (13th attempt) von Jay (@jsit) auf CodePen.

Unglaublich! Doppelt geprüft. Wie wäre es mit dem Punkt bei 87,5 % in unserem `background-image` (700 px), der mit der Position bei 33,333 % in unserer Bounding Box ausgerichtet ist?

p = (87.5% + (50% - 33.333%)/4 - 50%) × 4/(4 - 1) + 50%
p = 41.6667% × 1.333 + 50%
p = 105.555%

Siehe den Pen Background Focus: percentage (14th attempt) von Jay (@jsit) auf CodePen.

Sieht für mich gut genug aus!

Ich bin sicher, dass es für bestimmte Leute etwas Intuitives daran gibt, aber ich gehöre nicht dazu.

Lassen Sie uns eine Sass-Funktion erstellen, die all diese lächerlichen Berechnungen für uns durchführt.

Siehe den Pen Background Focus: percentage (final Sass function) von Jay (@jsit) auf CodePen.

Mir dreht sich der Kopf.

Als ich begann, dieses Problem anzugehen, erwartete ich nicht, dass es so schwierig sein würde, aber was für eine Reise. Ich hoffe, Sie durch meinen Denkprozess geführt zu haben, war aufschlussreich, und dass Sie vielleicht irgendwann Wert in unserer kleinen Sass-Funktion finden.

Alle in diesem Artikel eingebetteten Pens finden Sie in dieser Sammlung.