Platon Data Intelligence.
Vertikal sökning & Ai.

Rörliga bakgrunder

Datum:

Vi tänker ofta på bakgrundsbilder som textur eller något som ger kontrast för läsligt innehåll - med andra ord, inte riktigt innehåll. Om det var nöjd, skulle du förmodligen nå en <img> hur som helst, tillgänglighet och sånt.

Men det finns tillfällen då placera or skala av en bakgrundsbild kan sitta någonstans mellan polerna för innehåll och dekoration. Kontexten är kung, eller hur? Om vi ​​ändrar bakgrundsbildens position kan den förmedla lite mer sammanhang eller upplevelse.

Hur så? Låt oss titta på några exempel som jag har sett flyta runt.

När vi börjar kommer jag att varna för att det finns en fin linje i dessa demos mellan bilder som används för dekoration och bilder som används som innehåll. Skillnaden har implikationer för tillgänglighet där bakgrunder inte tillkännages för skärmläsare. Om din bild verkligen är en bild, då kanske överväga en <img> tagga med korrekt alt text. Och medan vi pratar tillgänglighet är det en bra idé att göra det överväga en användares rörelsepreferenser också.

Visa mig mer!

Chris Coyier har denna snygga lilla demo från flera år tillbaka.

Demon är superpraktisk på många sätt eftersom det är ett snyggt tillvägagångssätt för att visa annonser i innehåll. Du har försäljningsargument och en lockande bild för att komplettera den.

Den stora begränsningen för de flesta annonser, skulle jag satsa på, är den begränsade fastigheten. Jag vet inte om du någonsin har behövt släppa en annons på en sida, men jag har och brukar be annonsören om en bild som uppfyller exakta pixeldimensioner, så tillgången passar utrymmet.

Men Chris demo lindrar rymdfrågan. Håll muspekaren över bilden och se den både flytta och skala. Användaren får faktiskt mer kontext för produkten än de skulle ha när bilden var i sin ursprungliga position. Det är en win-win, eller hur? Annonsören får skapa en iögonfallande bild utan att kompromissa med sammanhanget. Samtidigt får användaren lite extra värde från de nyligen avslöjade delarna av bilden.

Om du kikar på demons markering kommer du att märka att det är i stort sett vad du kan förvänta dig. Här är en förkortad version:

<div class="ad-container"> <a href="#" target="_blank" rel="noopener"> <!-- Background image container --> <div class="ad-image"></div> </a> <div class="ad-content"> <!-- Content --> </div>
</div>

Vi skulle nog kunna käbbla lite över semantiken, men det är inte meningen. Vi har en container med en koppling <div> för bakgrundsbilden och en annan <div> att hålla innehållet.

När det gäller styling är de viktiga bitarna här:

.container { background-image: url("/path/to/some/image.png"); background-repeat: no-repeat; background-position: 0 0; height: 400px; width: 350px;
}

Inte illa, eller hur? Vi ger behållaren några dimensioner och sätter en bakgrundsbild på den som inte upprepas och som är placerad vid dess nedre vänstra kant.

Det verkliga tricket är med JavaScript. Vi kommer att använda det för att få muspositionen och behållarens offset, och sedan konvertera det värdet till en lämplig skala för att ställa in background-position. Låt oss först lyssna efter musrörelser på .container element:

let container = document.querySelector(".container");
container.addEventListener("mousemove", function(e) { // Our function }
);

Härifrån kan vi använda containerns offsetX och offsetY egenskaper. Men vi kommer inte att använda dessa värden direkt, eftersom värdet för X-koordinaten är mindre än vad vi behöver, och Y-koordinaten är större. Vi måste leka lite för att hitta en konstant som vi kan använda som multiplikator.

Det är lite touch-and-feel, men jag har hittat det 1.32 och 0.455 fungerar perfekt för X- respektive Y-koordinaterna. Vi multiplicerar offseten med dessa värden, lägg till a px enhet på resultatet, applicera den sedan på background-position värden.

let container = document.querySelector(".container");
container.addEventListener("mousemove", function(e) { container.style.backgroundPositionX = -e.offsetX * 1.32 + "px"; container.style.backgroundPositionY = -e.offsetY * 0.455 + "px"; }
);

Slutligen kan vi också återställa bakgrundspositionerna till originalet om användaren lämnar bildbehållaren.

container.addEventListener("mouseleave", function() { container.style.backgroundPosition = "0px 0px"; }
);

Eftersom vi är på CSS-Tricks, kommer jag att erbjuda att vi kunde ha gjort en mycket billigare version av detta med en liten svävningsövergång i vanilla CSS:

Måla en större bild

Utan tvekan har du varit i någon klädbutik online eller vad som helst och stött på den gamla zoom-på-sväva-funktionen.

Det här mönstret har funnits i vad som känns som en evighet (Dylan Winn-Brown delade med sig av sitt tillvägagångssätt tillbaka i 2016), men det är bara ett bevis (hoppas jag) på dess användbarhet. Användaren får mer sammanhang när de zoomar in och får en bättre uppfattning om en tröjas sömmar eller vad har du.

Det finns två delar till detta: den behållare och förstoringsglas. Behållaren är det enda vi behöver i uppmärkningen, eftersom vi kommer att injicera förstoringselementet under användarens interaktion. Så se vår HTML!

<div class="container"></div>

I CSS kommer vi att skapa width och height variabler för att lagra måtten på själva förstoringsglaset. Då ger vi det .containernågon form och en background-image:

​​:root {
​​ --magnifer-width: 85;
​​ --magnifer-height: 85;
​​} .container { width: 500px; height: 400px; background-size: cover; background-image: url("/path/to/image.png"); background-repeat: no-repeat; position: relative;
}

Det finns några saker vi redan vet om förstoringsglaset innan vi ens ser det, och vi kan definiera dessa stilar i förväg, särskilt de tidigare definierade variablerna för .maginifier's width och height:

.magnifier { position: absolute; width: calc(var(--magnifer-width) * 1px);
​​ height: calc(var(--magnifer-height) * 1px);
​​ border: 3px solid #000;
​​ cursor: none;
​​ background-image: url("/path/to/image.png");
​​ background-repeat: no-repeat;
}

Det är ett absolut placerat litet torg som använder Samma bakgrundsbildfil som .container. Observera att calc-funktionen endast används här för att konvertera det enhetslösa värdet i variabeln till pixlar. Ordna gärna det hur du tycker så långt som att eliminera upprepning i din kod.

Låt oss nu vända oss till JavaScript som samlar allt detta. Först måste vi komma åt CSS-variabeln som definierats tidigare. Vi kommer att använda detta på flera ställen senare. Då måste vi få muspositionen i behållaren eftersom det är värdet vi kommer att använda för förstoringsglasets bakgrundsposition.

​​// Get the css variables
​​let root = window.getComputedStyle(document.documentElement);
​​let magnifier_width = root.getPropertyValue("--magnifer-width");
​​let magnifier_height = root.getPropertyValue("--magnifer-height"); let container = document.querySelector(".container");
let rect = container.getBoundingClientRect();
let x = (e.pageX - rect.left);
let y = (e.pageY - rect.top); // Take page scrolling into account
x = x - window.pageXOffset;
y = y - window.pageYOffset;

Vad vi behöver är i grunden en mousemove evenemangslyssnare på .container. Sedan kommer vi att använda event.pageX or event.pageY egenskap för att få X- eller Y-koordinaten för musen. Men för att få exakt relativa positionen för musen på ett element, måste vi subtrahera positionen för det överordnade elementet från muspositionen vi får från JavaScript ovan. Ett "enkelt" sätt att göra detta är att använda getBoundingClientRect(), som returnerar storleken på ett element och dess position i förhållande till visningsporten.

Lägg märke till hur jag tar hänsyn till rullning. Om det finns spill, subtrahera fönstret pageX och pageY offset säkerställer att effekten fungerar som förväntat.

Vi kommer först att skapa förstoringsglaset div. Därefter kommer vi att skapa en mousemove funktion och lägg till den i bildbehållaren. I den här funktionen kommer vi att ge förstoraren ett klassattribut. Vi kommer också att beräkna muspositionen och ge förstoringsglaset de vänstra och översta värdena som vi beräknat tidigare.

Låt oss gå vidare och bygga magnifier när vi hör a mousemove händelse på .container:

// create the magnifier
let magnifier = document.createElement("div");
container.append(magnifier);

Nu måste vi se till att den har ett klassnamn som vi kan omfånga till CSS:en:

// run the function on `mousemove`
container.addEventListener("mousemove", (e) => { magnifier.setAttribute("class", "magnifier");
}

Exempelvideon jag visade tidigare placerar förstoringsglaset utanför behållaren. Vi kommer att hålla det här enkelt och lägga det ovanpå behållaren istället när musen rör sig. Vi kommer använda if för att endast ställa in förstoringsglasets position om X- och Y-värdena är det större or lika till noll, och mindre än behållarens bredd eller höjd. Det borde hålla det inom gränserna. Se bara till att subtrahera förstoringsglasets bredd och höjd från X- och Y-värdena.

// Run the function on mouse move.
container.addEventListener("mousemove", (e) => { magnifier.setAttribute("class", "magnifier"); // Get mouse position let rect = container.getBoundingClientRect(); let x = (e.pageX - rect.left); let y = (e.pageY - rect.top); // Take page scrolling into account x = x - window.pageXOffset; y = y - window.pageYOffset; // Prevent magnifier from exiting the container // Then set top and left values of magnifier if (x >= 0 && x <= container.clientWidth - magnifier_width) { magnifier.style.left = x + "px"; } if (y >= 0 && y <= container.clientHeight - magnifier_height) { magnifier.style.top = y + "px"; }
});

Sist men absolut inte minst... vi måste leka lite med förstoringsglasets bakgrundsbild. Hela poängen är att användaren får en STÖRRE bild av bakgrundsbilden baserat på var hovringen äger rum. Så låt oss definiera ett förstoringsglas som vi kan använda för att skala upp saker. Sedan definierar vi variabler för bakgrundsbildens bredd och höjd så att vi har något att basera skalan på, och ställer in alla dessa värden på .magnifier stilar:

// Magnifier image configurations
let magnify = 2;
let imgWidth = 500;
let imgHeight = 400; magnifier.style.backgroundSize = imgWidth * magnify + "px " + imgHeight * magnify + "px";

Låt oss ta X- och Y-koordinaterna för förstorarens bild och tillämpa dem på .magnifierelementets background-position. Som tidigare med förstoringsglaset måste vi subtrahera förstoringsglasets bredd och höjd från X- och Y-värdena med hjälp av CSS-variablerna.

// the x and y positions of the magnifier image
let magnify_x = x * magnify + 15;
let magnify_y = y * magnify + 15; // set backgroundPosition for magnifier if it is within image
if ( x <= container.clientWidth - magnifier_width && y <= container.clientHeight - magnifier_height
) { magnifier.style.backgroundPosition = -magnify_x + "px " + -magnify_y + "px";
}

Tada!

Gör det filmiskt

Har du sett Ken Burns-effekt? Det är en klassisk och tidlös sak där en bild är större än behållaren den är i, sedan glider och fjälls långsamt som en snigel. Nästan alla dokumentärfilmer i världen verkar använda den för stillbilder. Om du har en Apple TV har du säkert sett den på skärmsläckaren.

Det finns gott of exempel på CodePen om du vill få en bättre uppfattning.

Du kommer att se att det finns ett antal sätt att närma sig detta. Vissa använder JavaScript. Andra är 100 % CSS. Jag är säker på att JavaScript-metoderna är bra för vissa användningsfall, men om målet helt enkelt är att subtilt skala bilden, är CSS perfekt lämplig.

Vi skulle kunna piffa till lite med flera bakgrunder istället för en. Eller ännu bättre, om vi utökar reglerna till att använda element istället för bakgrundsbilder, kan vi använda samma animation på alla bakgrunder och använda ett streck animation-delay för att förskjuta effekten.

Många sätt att göra detta på, såklart! Det kan säkert optimeras med Sass- och/eller CSS-variabler. Heck, kanske du kan klara det med en singel <div> Om så är fallet, dela det i kommentarerna!

Bonus: Gör det uppslukande

Jag vet inte om något är coolare än Sarah Drasners "Happy Halloween" penna… och det är från 2016! Det är ett bra exempel på att lager bakgrunder och flyttar dem i olika hastigheter för att skapa en nästan filmisk upplevelse. Herregud vad coolt är det!

GSAP är huvuddrivkraften där, men jag föreställer mig att vi skulle kunna göra en nedkokt version som helt enkelt översätter varje bakgrundslager från vänster till höger med olika hastigheter. Inte lika coolt, naturligtvis, men definitivt grundupplevelsen. Måste se till att början och slutet av varje bakgrundsbild är konsekvent så att den upprepas sömlöst när animeringen upprepas.


Det var allt för nu! Ganska snyggt att vi kan använda bakgrunder till mycket mer än textur och kontrast. Jag är helt säker på att det finns massor av andra smarta interaktioner som vi kan tillämpa på bakgrunder. Temani Afif gjorde precis det med ett gäng snygga svävningseffekter för länkar. Vad har du i åtanke? Dela det med mig i kommentarerna!

plats_img

Senaste intelligens

plats_img

Chatta med oss

Hallå där! Hur kan jag hjälpa dig?