CSS-mediatyypit ja mediakyselyt
Tutustutaan mediatyyppeihin ja mediakyselyihin, joilla samasta dokumentista saadaan erilainen eri ympäristöissä: kapealla ja leveällä näytöllä, tulostettuna ja käyttäjän omien asetusten mukaan.
Tämän luennon jälkeen sinun pitäisi osata:
- kertoa, mitkä mediatyypit ovat käytössä ja mitkä eivät;
- kohdistaa tyylejä
media-attribuutilla ja@media-säännöllä; - kirjoittaa leveyteen perustuvia mediakyselyjä ja perustella katkaisukohtien yksikön;
- selittää, mitä mobile first tarkoittaa ja miksi niin kannattaa tehdä;
- reagoida käyttäjän asetuksiin kyselyillä
prefers-color-schemejaprefers-reduced-motion; - tehdä sivusta tulostettavan version;
- käyttää
viewport-määritystä oikein.
Tämä luento jatkaa CSS-luennon asioita. Erityisesti kaskadi ja mittayksiköt kannattaa olla mielessä.
1. Mediatyypit
Mediatyypillä kerrotaan, millaiselle laitteelle tyylit on tarkoitettu. Samasta dokumentista voidaan siis tehdä erinäköinen paperille kuin näytölle, ilman että sisältöä tarvitsee kirjoittaa kahteen kertaan.
1.1 Käytettävissä olevat mediatyypit
| Tyyppi | Tarkoitus |
|---|---|
all | Kaikki laitteet. Tämä on oletus, jos tyyppiä ei anneta |
screen | Näyttölaitteet |
print | Tulostus ja tulostuksen esikatselu |
Vanhoissa ohjeissa luetellaan tyyppejä kuten tv,
projection, handheld, braille,
tty ja aural. Media Queries Level 4 on poistanut ne, eivätkä
ne osu enää mihinkään. Jos kirjoitat @media handheld, sääntöjä ei
sovelleta millään laitteella.
Myös speech-tyyppi on määritelty, mutta yksikään selain ei
toteuta sitä. Ruudunlukija lukee sivun screen-tyyleillä, joten
saavutettavuutta ei voi parantaa @media speech -säännöillä. Se tehdään
oikealla HTML-rakenteella.
1.2 Mediatyypin määrittäminen
Tyylit voidaan kohdistaa kahdella tavalla. Ensimmäinen on
link-elementin media-attribuutti:
<link rel="stylesheet" href="tulostus.css" media="print" />
Toinen on @media-sääntö tyylitiedoston sisällä. Tämä on nykyisin
tavallisempi, koska kaikki tyylit pysyvät yhdessä tiedostossa:
@media print {
/* tähän kaikki tulostukseen liittyvät tyylit */
}
Vanhoissa ohjeissa varoitetaan linkittämästä all-median tyylejä
muiden jälkeen, koska ne muka "ylikirjoittaisivat" muut. Kyse ei ole
mediatyypistä: mediatyyppi ei vaikuta spesifisyyteen lainkaan.
Kun kaksi sääntöä osuu samaan elementtiin ja niiden spesifisyys on sama, voittaa
myöhemmin kirjoitettu. Katso
CSS-luennon
luku 3.
Käytännön sääntö on siis sama kuin muutenkin: yleiset säännöt ensin, poikkeukset perään.
link-elementille title-attribuuttia
title-attribuutti tekee tyylistä vaihdettavan, jolloin selain ei
välttämättä ota sitä käyttöön automaattisesti. Tulostustyyleissä tämä näkyy siten,
ettei tulostuksen esikatselu käytä niitä lainkaan.
2. Mediakyselyt
Mediakyselyllä (media query) tarkennetaan, millaisessa tilanteessa tyylejä käytetään. Kysely on ollut W3C:n suositus vuodesta 2012, ja se on nykyisin responsiivisen sivun perustyökalu.
Kyselyllä voi tarkastella muun muassa näyttöalueen leveyttä ja korkeutta, median suuntaa (pysty vai vaaka), kuvasuhdetta, resoluutiota sekä käyttäjän omia asetuksia. Ylivoimaisesti käytetyin on leveys.
2.1 Leveyteen perustuvat kyselyt
/* Voimassa, kun näkymäikkuna on vähintään 30em leveä */
@media (min-width: 30em) {
/* tyylit tähän */
}
/* Voimassa, kun näkymäikkuna on enintään 30em leveä */
@media (max-width: 30em) {
/* tyylit tähän */
}
Mediatyypin voi jättää pois, kun kysely koskee kaikkia laitteita.
@media (min-width: 30em) on siis sama kuin
@media all and (min-width: 30em), mutta lyhyempi ja luettavampi.
Mediatyyppi kirjoitetaan vain silloin, kun sitä oikeasti tarvitaan, esimerkiksi
@media print and (min-width: 20cm).
em-yksikköä
Pikselimittainen katkaisukohta ei ota huomioon sitä, että käyttäjä on voinut suurentaa selaimensa oletusfonttikokoa. Silloin teksti kasvaa mutta asettelu ei vaihdu, ja sivu ahtautuu.
Mediakyselyssä 1em tarkoittaa aina selaimen
oletusfonttikokoa, eikä siihen vaikuta se, mitä olet määritellyt
html- tai body-elementille. Tavallisella asetuksella
30em on noin 480 pikseliä ja 60em noin 960 pikseliä.
2.2 Mobile first
Kyselyt voi kirjoittaa kahteen suuntaan, ja suunnalla on iso merkitys tyylitiedoston rakenteeseen.
| Mobile first (suositus) | Desktop first | |
|---|---|---|
| Perustyyli | Kapealle näytölle, ilman mediakyselyä | Leveälle näytölle, ilman mediakyselyä |
| Kyselyt | min-width: lisätään ominaisuuksia tilan kasvaessa |
max-width: puretaan ominaisuuksia tilan kaventuessa |
| Jos kysely ei toimi | Käyttäjä saa yksinkertaisen mutta toimivan version | Käyttäjä saa leveän version kapealle näytölle |
Mobile first -tapa on suositeltavampi kahdesta syystä. Yksinkertaisin versio on turvallisin oletus, ja ominaisuuksien lisääminen on helpompaa kuin niiden purkaminen. Kapealla näytöllä kannattaa muutenkin pyrkiä yksinkertaiseen esitykseen ja sijoittaa asiat mieluummin peräkkäin kuin vierekkäin.
Vanhoissa esimerkeissä näkee ratkaisuja kuten
header { display: none; } kapealle näytölle. Puhelinkäyttäjä ei ole
toisen luokan käyttäjä, eikä hänelle saa tarjota vähemmän sisältöä. Järjestä
sisältö uudelleen sen sijaan, että piilotat sen.
Kapealla näytöllä on lisäksi huolehdittava siitä, ettei sivua tarvitse vierittää sivusuunnassa. Tavallisimmat syyt vaakavieritykseen ovat liian leveä kuva, taulukko tai koodilohko:
img {
max-width: 100%;
height: auto;
}
pre {
overflow-x: auto; /* vierityspalkki vain kun sitä tarvitaan */
}
2.3 Esimerkki
Muuta selainikkunan leveyttä ja katso, miten laatikon väri vaihtuu. Kokeile myös muuttaa katkaisukohtia CSS-kentässä.
2.4 Mediakyselyjen testaaminen
Kehittäjätyökaluissa on laitenäkymä, jolla sivua voi katsella eri levyisenä ilman että selainikkunaa tarvitsee raahata. Se avautuu näppäinyhdistelmällä Ctrl+Shift+M (macOS: Cmd+Shift+M) sen jälkeen, kun työkalut on avattu F12-näppäimellä. Katso HTML5-luennon luku 19.4.
Tarkista aina vähintään noin 360 pikselin leveydellä. Muista, että laitenäkymä jäljittelee vain kokoa: oikealla laitteella kannattaa kokeilla lopuksi.
3. Käyttäjän asetuksiin reagoivat kyselyt
Osa mediakyselyistä ei kysy laitteesta vaan siitä, mitä käyttäjä on käyttöjärjestelmästään valinnut. Nämä ovat helppoja toteuttaa ja parantavat saavutettavuutta selvästi.
3.1 prefers-color-scheme
Kysely kertoo, onko käyttäjä valinnut vaalean vai tumman tilan. Arvot ovat
light ja dark.
/* Perustyyli on vaalea ja toimii aina. */
body {
background-color: #ffffff;
color: #23201c;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #1c1a17;
color: #f2eee7;
}
}
Lisäksi kannattaa kertoa selaimelle, että sivu tukee molempia tiloja. Silloin myös lomakekentät, vierityspalkit ja muut selaimen omat osat mukautuvat:
:root {
color-scheme: light dark;
}
Vaatimus 4,5:1 koskee kumpaakin tilaa erikseen. Tumman tilan yleisin virhe on täysin musta tausta ja täysin valkoinen teksti, mikä on monille epämiellyttävän kirkas. Käytä hyvin tummaa harmaata ja hieman murrettua valkoista.
3.2 prefers-reduced-motion
Osa käyttäjistä saa liikkuvasta kuvasta huimausta tai pahoinvointia, ja osalle
liike vaikeuttaa keskittymistä. Käyttöjärjestelmissä on asetus, jolla liikettä
pyydetään vähentämään, ja selain välittää sen tällä kyselyllä. Arvot ovat
reduce ja no-preference.
Kirjoita animaatio kyselyn sisään, älä sen ulkopuolelle:
/* Oikein: liikettä ei ole oletuksena, vaan se lisätään
vain jos käyttäjä ei ole pyytänyt sen vähentämistä. */
@media (prefers-reduced-motion: no-preference) {
.kortti {
transition: transform 0.3s ease;
}
}
/* Väärin: animaatio on aina päällä, ja se poistetaan erikseen.
Selaimessa, joka ei tue kyselyä, liike jää päälle. */
.kortti {
transition: transform 0.3s ease;
}
@media (prefers-reduced-motion: reduce) {
.kortti {
transition: none;
}
}
Kirjoita perustyyliksi se vaihtoehto, joka on turvallisin, ja lisää muut kyselyillä. Näin sivu toimii järkevästi myös silloin, kun kyselyä ei tueta tai tyylitiedosto latautuu vain osittain.
Muita saman perheen kyselyjä ovat prefers-contrast ja
forced-colors, joka kertoo Windowsin suurkontrastitilasta.
4. Tulostustyylit
Tulostettu sivu on eri media kuin näyttö. Navigointivalikkoja ei voi klikata paperilla, taustavärit kuluttavat mustetta ja linkkien osoitteet eivät näy mitenkään. Muutamalla säännöllä sivusta saa siistin tulosteen.
@media print {
/* Piilotetaan se, mikä ei toimi paperilla */
nav, footer, .mainos {
display: none;
}
/* Näytetään linkin osoite sulkeissa linkkitekstin perässä */
main a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.9em;
}
/* Vältetään sivunvaihtoa hankalissa kohdissa */
h1, h2, h3 {
break-after: avoid;
break-inside: avoid;
}
ul, ol, dl, img, table {
break-inside: avoid;
}
}
4.1 Sivunvaihdon hallinta
| Ominaisuus | Merkitys |
|---|---|
break-before | Sivunvaihto ennen elementtiä |
break-after | Sivunvaihto elementin jälkeen |
break-inside | Sivunvaihto elementin sisällä |
| Arvo | Merkitys |
|---|---|
auto | Selain päättää. Oletus |
avoid | Vältä sivunvaihtoa tässä kohtaa |
page | Pakota sivunvaihto |
left, right | Pakota sivunvaihto niin, että seuraava sivu on vasen tai oikea |
page-break-*-ominaisuudet
Aiemmin käytettiin ominaisuuksia page-break-before,
page-break-after ja page-break-inside. Ne toimivat yhä,
koska selaimet muuntavat ne uusiksi, mutta uusissa tyyleissä kannattaa käyttää
muotoja break-*. Huomaa myös, että vanha arvo always
vastaa uutta arvoa page.
Avaa tulostuksen esikatselu (Ctrl+P). Kehittäjätyökaluissa voit myös pakottaa tulostusmedian: avaa komentopaletti ja etsi kohta Emulate CSS media type: print, jolloin sivu näkyy tulostustyyleillä selainikkunassa ja voit tutkia sitä normaalisti.
5. Viewport
Mobiililaitteet olettavat oletusarvoisesti, että sivu on suunniteltu leveälle näytölle. Esimerkiksi Applen laitteet olettavat sivun olevan noin 980 pikseliä leveä ja kutistavat sen näytölleen. Jos sivu on tehty responsiiviseksi, tämä arvaus vain pilaa lopputuloksen: teksti kutistuu pieneksi eivätkä mediakyselyt osu oikein.
Sen estämiseksi dokumentin head-osaan kirjoitetaan:
<meta name="viewport" content="width=device-width, initial-scale=1" />
| Osa | Merkitys |
|---|---|
width=device-width |
Näkymäikkunan leveydeksi asetetaan laitteen todellinen leveys eikä kiinteää arvoa |
initial-scale=1 |
Sivu avataan zoomaamattomana |
Määrityksiä user-scalable=no, maximum-scale ja
minimum-scale näkee vanhoissa ohjeissa. Älä käytä niitä.
Ne estävät sivun suurentamisen, mikä on suoraan saavutettavuusvaatimuksen vastaista
ja tekee sivusta käyttökelvottoman heikkonäköiselle. Käytä vain kahta yllä olevaa
osaa.
Kauttaviiva kuuluu attribuutin arvon ulkopuolelle. Alla oleva rivi on virheellinen, koska kauttaviiva on lainausmerkkien sisällä eikä elementtiä suljeta lainkaan:
<meta name="viewport" content="width=device-width, initial-scale=1 /">
Oikein:
<meta name="viewport" content="width=device-width, initial-scale=1" />
Jos et tee responsiivista sivua, älä käytä viewport-määritystä lainkaan.
Silloin laitteen oma sovitus on parempi kuin puolivalmis responsiivisuus. Tällä
kurssilla sivut tehdään responsiivisiksi, joten määritys kuuluu jokaisen sivun
head-osaan.
6. Tarkistuslista
- Onko jokaisen sivun
head-osassa oikein kirjoitettuviewport-määritys? - Onko zoomaus sallittu, eli puuttuvatko
user-scalablejamaximum-scale? - Ovatko katkaisukohdat
em-yksikössä pikselien sijaan? - Onko perustyyli kirjoitettu kapealle näytölle ja lisäykset
min-width-kyselyillä? - Toimiiko sivu noin 360 pikselin levyisellä näytöllä ilman vaakavieritystä?
- Onko kaikki sisältö saatavilla myös kapealla näytöllä, eli et ole piilottanut
mitään
display: none-määrityksellä? - Onko kontrasti riittävä sekä vaaleassa että tummassa tilassa?
- Onko mahdollinen liike kirjoitettu
prefers-reduced-motion: no-preference-kyselyn sisään? - Näyttääkö tulostuksen esikatselu järkevältä?
7. Lisätietoa
- MDN: Using media queries ja MDN: @media.
- MDN: prefers-color-scheme ja MDN: prefers-reduced-motion.
- Media Queries Level 4, varsinainen määrittely.
- MDN: viewport meta tag.
- Responsive web design basics (web.dev).
- A tale of two viewports, perusteellinen selitys siitä, mitä viewport oikeastaan tarkoittaa.
Käyttäjien kommentit