Stablet “Grenser”

0
17

En liten stund tilbake, og jeg var i ferd med å legge fokus stiler til Et Event Apart ‘ s hjemmeside. En del av dette var å anvende ulike fokus virkninger i ulike områder av design, som hvite ringer i topp-og bunntekst og oransje ringer i hovedteksten. Men på ett sted, jeg ønsket ringer som var mer opplagt noe som du legger dem i bunker to kanter på toppen av hverandre, for å skape uvanlige former som ville fange øyet.

Jeg lekt med tanken på å hekkende elementer med grenser og noen negative marginer å trekke en grense på toppen av en annen, eller hekkende en ramme inne i en oversikt, og deretter bruke negative marginer for å holde fra å kaste av layout. Men ingen av som følte tilfredsstillende.

Det viser seg at det finnes en rekke triks for å skape effekten av stabling en ramme på toppen av en annen ved å kombinere en ramme med noen andre CSS-effekter, eller selv uten faktisk krever bruk av noen grenser i det hele tatt. La oss utforske, skal vi?

Skissere og box-shadow

Hvis ting å være multi-grenser er et rektangel—du vet, som ganske mye alle blokkere elementer—deretter blande en oversikt og en spredt ut hardt boksen skygge kan være akkurat den tingen.

La oss starte med boksen skygge. Du er sannsynligvis vant til boksen skygger som dette:

.drop-me {
bakgrunn: #AEA;
box-shadow: 10px 12px 0.5 rem rgba(0,0,0,0.5);
}

Som får deg en uklar skygge under og til høyre for element. Skygger, så forrige årtusen! Men det er rom, og støtte, for en fjerde lengde verdi i box-shadow som definerer en spredning avstand. Dette øker størrelsen på shadow form i alle retninger av gitt lengde, og da er det uskarpt. Forutsatt at det er en flekk, som er.

Så hvis vi gir en boks shadow ingen offset, ingen uskarphet, og litt spredt, det vil trekke seg rundt elementet, og ser ut som en solid ramme uten faktisk å være en ramme.

.boxborder-me {
box-shadow: 0 0 0 5px firebrick;
}

Denne box-shadow “grensen” er blitt trukket like utenfor den ytre grensen kanten av elementet. Det er samme sted skisserer bli dratt rundt blokken bokser, så alt vi trenger å gjøre nå er å tegne et omriss over skyggen. Noe sånt som dette:

.boxborder-me {
box-shadow: 0 0 0 5px firebrick;
disposisjon: stiplede 5px darkturquoise;
}

Bingo. En flerfarget “grensen”, som i dette tilfellet, ikke engang kaste av layout størrelse, fordi skygger og skisserer er trukket etter element størrelse er beregnet. Omrisset, som sitter på toppen, kan bruke ganske mye alle outline-stil, som er det samme som listen over grensen stiler. Dermed, prikkete og dobbel skisserer er det muligheter. (Så er alle de andre stiler, men de har ikke noen gjennomsiktige deler, så solid skygge kan bare sees gjennom gjennomskinnelige farger.)

Hvis du vil ha et tre-tone-effekt på grensen, flere safe skygger kan opprettes ved hjelp av en komma-separert liste, og deretter en oversikt sette over toppen. For eksempel:

.boxborder-me {
box-shadow: 0 0 0 1px darkturquoise,
0 0 0 3px firebrick,
0 0 0 5px oransje,
0 0 0 6px darkturquoise;
disposisjon: stiplede 6px darkturquoise;
}

Tar det tilbake til enklere effekter, som kombinerer en stiplet omriss over et spredt boksen skyggen med en solid ramme av samme farge som den boksen skygge skaper likevel en annen effekt:

.boxborder-me {
box-shadow: 0 0 0 5px firebrick;
disposisjon: stiplede 5px darkturquoise;
border: solid 5px darkturquoise;
}

Den ekstra bonus her er at selv om en boks skygge blir brukt, betyr det ikke fyll i elementet er bakgrunnen, slik at du kan se bakteppe gjennom det. Dette er hvordan boksen skygger alltid oppføre seg: de er bare trukket utenfor den ytre grensen kanten. “Resten av skyggen,” den delen du kan anta er alltid bak element, ikke eksisterer. Det er aldri trukket. Så får du resultater som dette:

Dette er resultatet av støtende språk i CSS Bakgrunnen og kantene Modul, Nivå 3, avsnitt 7.1.1:

En ytre box-shadow kaster en skygge som om grensen-boksen av elementet var ugjennomsiktig. Forutsatt en spredning avstand på null, dens omkrets har nøyaktig samme størrelse og form som grensen boksen. Skyggen er trukket utenfor grensen kanten bare: det er festet på innsiden av grensen-boksen av elementet.

(Uthevelse tilføyd.)

Grensen og box-shadow

Snakker av grenser, kanskje det er en måte å kombinere grenser og safe skygger. Tross alt, safe skygger kan være mer enn bare skygger. De kan også være inset. Så hva om vi snudde tidligere skygge innover, og droppet en kant over toppen av det?

.boxborder-me {
box-shadow: 0 0 0 5px firebrick inset;
grensen: stiplede 5px darkturquoise;
}

Det er… ikke hva vi var ute etter. Men dette er hvordan inset skygger arbeid: de er trukket inne i den ytre polstring kanten (også kjent som den indre grensen kant), og klippet utover at:

En indre box-shadow kaster en skygge som om alt utenfor polstring kanten var ugjennomsiktig. Forutsatt en spredning avstand på null, dens omkrets har nøyaktig samme størrelse og form som den padding-boksen. Skyggen er trukket innvendig polstring kanten bare: det er festet utenfor polstring boksen av elementet.

(Ibid; uthevelse tilføyd.)

Så vi kan ikke stable en ramme på toppen av en innfelt box-shadow. Kanskje vi kunne stable en ramme på toppen av noe annet…?

Grensen og flere bakgrunner

Inset skygger kan være begrenset til den ytre polstring kanten, men bakgrunner er ikke. Et element er bakgrunnen vil, som standard, fylle området ut til den ytre grensen kanten. Fyll et element bakgrunn med heldekkende farge, gi det en tykk stiplet ramme, og du vil se bakgrunnsfarge mellom den synlige deler av grensen.

Så hva om vi ser noen bakgrunner på toppen av hverandre, og dermed trekke solid farge vi ønsker bak grensen? Her er trinn én:

.multibg-me {
grensen: 5px stiplede firebrick;
bakgrunn:
linear-gradient(til høyre, darkturquoise, 5px, gjennomsiktig 5px);
background-origin: border-box;
}

Vi kan se, er det på venstre side, på blå bakgrunn som er synlig gjennom den transparente deler av stiplet rød kant. Legg til tre mer sånn, en for hver kant av element-boksen, og:

.multibg-me {
grensen: 5px stiplede firebrick;
bakgrunn:
linear-gradient(til toppen, darkturquoise, 5px, gjennomsiktig 5px),
linear-gradient(til høyre, darkturquoise, 5px, gjennomsiktig 5px),
linear-gradient(til bunnen, darkturquoise, 5px, gjennomsiktig 5px),
linear-gradient(til venstre, darkturquoise, 5px, gjennomsiktig 5px);
background-origin: border-box;
}

I hvert enkelt tilfelle, på bakgrunn gradient går for fem punkter som en solid mørk turkis bakgrunn, og deretter har en farge stoppe overganger som umiddelbart til gjennomsiktig. Dette gjør at de “bakteppe” vis gjennom elementet mens du fortsatt å gi oss en “stablet grensen”.

En stor fordel her er at vi ikke er begrenset til solid lineær graderinger—vi kan bruke alle fall på noen kompleksitet, bare for å krydre ting opp litt. Ta dette eksemplet, der den stiplede grensen har blitt gjort for det meste gjennomsiktig, slik at vi kan se fire ulike graderinger i sin helhet:

.multibg-me {
grensen: 15 piksler stiplede rgba(128,0,0,0.1);
bakgrunn:
linear-gradient(til toppen, darkturquoise, røde 15 piksler, gjennomsiktig 15 piksler),
linear-gradient(til høyre, darkturquoise, røde 15 piksler, gjennomsiktig 15 piksler),
linear-gradient(til bunnen, darkturquoise, røde 15 piksler, gjennomsiktig 15 piksler),
linear-gradient(til venstre, darkturquoise, røde 15 piksler, gjennomsiktig 15 piksler);
background-origin: border-box;
}

Hvis du ser på hjørnene, vil du se at bakgrunnen graderinger er rektangulære, og overlapper hverandre. De trenger ikke møte opp pent, måten grensen hjørner gjøre. Dette kan være et problem hvis grensen har gjennomsiktige delene i hjørnene, som ville være tilfellet med border-style: double.
Også, hvis du bare ønsker en solid farge bak grensen, dette er en ganske klønete måte å sy sammen den effekten. Sikkert må det være en bedre tilnærming?

Ramme og bakgrunn klipping

Ja, det er det! Det innebærer å endre klipping bokser for to forskjellige lag av elementet bakgrunn. Det første som kan våren til sinnet er noe sånt som dette:

.multibg-me {
grensen: 5px stiplede firebrick;
background: #EEE, darkturquoise;
bakgrunn-klipp: padding-boksen, border-box;
}

Men det fungerer ikke, fordi CSS krever at bare den siste (og dermed lavest) bakgrunn settes til <farge> verdi. Andre bakgrunnslaget må være et bilde.

Så vi sett at svært lys-grå bakgrunnsfarge med en gradient fra farge til farge: dette fungerer fordi graderinger er bilder. Med andre ord:

.multibg-me {
grensen: 5px stiplede firebrickred;
bakgrunn: linear-gradient(til toppen, #EEE, #EEE), darkturquoise;
bakgrunn-klipp: padding-boksen, border-box;
}

Lys grå “gradient” fyller hele bakgrunnen området, men er festet til padding boksen med bakgrunn-klipp. Mørk turkis fyller hele området og er festet til grensen boksen, som bakgrunn har alltid vært standard. Vi kan endre gradient farger og retning til noe vi liker, og skaper en faktisk synlig fargeovergang eller flytter den til alle-hvitt eller hva andre lineære effekten vi ønsker.

Ulempen her er at det er ingen måte å gjøre det padding-området bakgrunnen, transparent slik at elementet bakteppe kan bli sett gjennom elementet. Hvis lineær gradient er laget gjennomsiktig, da hele elementet bakgrunn vil bli fylt med mørk turkis. Eller, mer presist, vil vi være i stand til å se mørk turkis, som alltid var der.

I mange tilfeller spiller det ingen rolle at elementet bakgrunn ikke se gjennom, men det er fortsatt en frustrerende begrensning. Er ikke det noen måte å få effekt av stablet grenser uten sprø hacks og tapte muligheter?

Grensen bilder

Faktisk, hva om vi kunne ta et bilde av stabelen grensen vi ønsker å se i verden, skjær den opp, og bruke det som grensen? Som, si, dette bildet blir denne grensen?

Her er koden for å gjøre akkurat det:

.borderimage-me {
border: solid 5px;
grensen-image: url(triple-stack-border.gif) 15 / 15 piksler runde;
}

Først, vi sette en fast grense med noen bredde. Vi kan også angi en farge for tilbakefall formål, men det er egentlig ikke nødvendig. Da vi peker på et bilde-URL, definere skive inset(s) på 15 og bredde på grensen til å være 15 piksler, og til slutt gjenta mønster av runden.

Det finnes flere alternativer for grensen bilder, som er litt for komplisert til å komme inn her, men resultatet er at du kan ta et bilde, angi ni stykker av det ved hjelp av offset verdier, og har de bildene som brukes til å syntetisere en komplett ramme rundt et bilde. Det er gjort ved å definere kvoter fra kantene av bildet selv, som i dette tilfellet er 15. Siden bilde er en GIF-og dermed pixel-basert, kvotene er i punkter, slik at “slice linjer” er satt til 15 punkter innover fra kanten av bildet. (I tilfelle av en SVG, kvotene er målt i form av SVG er koordinatsystem.) Det ser ut som dette:

Hver skive er tilordnet til hjørne eller på siden av elementet boksen som svarer til seg selv, dvs., nederst i høyre hjørne slice er plassert i nederst høyre hjørne av elementet, toppen (i midten) slice er brukt langs den øverste kanten av elementet, og så videre.

Hvis en av kanten skiver er mindre enn kanten av elementet er lang—som nesten alltid skjer, og er sikkert sant her—så stykket er gjentatt i en av en rekke måter. Jeg valgte runde, som fyller i så mange gjentar som det kan, og deretter skalere dem opp alle sammen akkurat nok til å fylle ut den kanten. Så med en 70-pixel-langt stykke, hvis den kanten er 1,337 punkter lenge, vil det være 19 repetisjoner av stykket, som hver er skalert til å være 70.3 piksler bred. Eller, mer sannsynlig, nettleseren genererer et enkelt bilde som inneholder 19 repetisjoner som er 1,330 piksler bred, og deretter strekker seg at bildet de ekstra 7 punkter.

Du kanskje tror ulempen her er nettleser støtter, men som viser seg ikke å være tilfelle.

Denne nettleseren støtter data er fra Caniuse, som har mer detalj. Angir et nummer som nettleseren støtter funksjonen på denne versjonen, og opp.

Skrivebordet

ChromeOperaFirefoxIEEdgeSafari
56 43 50 11 12 9.1

Mobil / Nettbrett

iOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox
9.3 46 alle* 67 71 64

Bare se opp for noen bugs (virkelig, gjennomføring grenseverdier) som lurer rundt et par implementeringer, og du blir fin.

Konklusjon

Mens det kan være en sjelden situasjon der du ønsker å kombinere flere “grensen” – effekter, eller stable dem oppå hverandre, er det godt å vite at CSS gir en rekke måter for å få jobben gjort, og at de fleste av dem er allerede utbredt støtte. Og hvem vet? Kanskje en dag vil det være en enkel måte for å oppnå disse typer effekter gjennom en enkelt eiendel, i stedet for ved å blande flere sammen. Inntil da, glad grensen stabling!