Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Immagini SVG responsive con le mediaquery

In SVG la struttura stessa dell'oggetto può essere resa responsive, grazie alle media query CSS3 possiamo creare immagini vettoriali e responsive!
In SVG la struttura stessa dell'oggetto può essere resa responsive, grazie alle media query CSS3 possiamo creare immagini vettoriali e responsive!
Link copiato negli appunti

Un layout responsive (o reattivo) non implica solo che i suoi elementi abbiano dimensioni variabili, ma che questi vengano resi diversamente in base a determinate caratteristiche della periferica dell'utente.

In SVG è la struttura stessa dell'oggetto che può essere resa responsive, grazie al ricorso alle funzionalità più avanzate di CSS3. In questa lezione approfitteremo delle media query CSS3 per creare immagini vettoriali e responsive.

L'immagine di partenza

Il fine è quello di scomporre un'immagine in parti indipendenti affinché queste possano essere rese diversamente in base alle dimensioni della viewport. Il presupposto, quindi, è dato dalla disponibilità di un'immagine SVG ben strutturata.

Per i nostri esempi, abbiamo modificato un'immagine che rappresenta un segnale stradale, disponibile gratuitamente su Wikimedia. L'immagine sarà modificata per apparire come nella figura che segue:

Cartello stradale

La struttura generale del mark-up di questa immagine sarà il seguente:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg>
	<g id="cartello-superiore">
 		<path ... />
		<path ... />
		<path ... />
	</g>
	<path id="canguro" />
	<g id="cartello-inferiore">
		<rect ... />
		<rect ... />
		<rect ... />
		<text ... >NEXT</text>
		<text ... >20</text>
		<text ... >km</text>
	</g>
</svg>

L'immagine si compone di tre parti:

  • la forma quadrata inclinata del cartello superiore, individuata dall'elemento g#cartello-superiore;
  • il canguro, definito dall'elemento path#canguro;
  • la forma rettangolare inferiore con il testo, generata dal gruppo g#cartello-inferiore.

Le dimensioni dell'elemento SVG saranno determinanti per la corretta resa a video. Eviteremo l'attributo height, mentre assegneremo il valore 100% all'attributo width. Andando, poi, ad impostare un rapporto costante tra le dimensioni con l'attributo viewBox, allora l'immagine si adatterà automaticamente alla viewport.
Modifichiamo, quindi, l'elemento svg dell'immagine come segue:

<svg
	...
	width="100%"
	viewBox="-1 0 121.97654 180.21942"
	... >

La struttura HTML

Supponiamo di voler creare un header costituito da un'immagine sulla sinistra e dal titolo della pagina sulla destra:

<header id="logo">
	<object type="image/svg+xml" id="cartello" data="cartello.svg">
		<div>Cartello</div>
	</object>
	<h1 id="site-title">Australia road signs</h1>
</header>

L'immagine SVG avrà una viewport specifica, che potrà non corrispondere alla viewport della pagina. La viewport SVG sarà data, infatti, dalle dimensioni del container, che in questo caso è l'elemento object.

Bisognerà tener conto di questa particolarità quando imposteremo i break-point delle media query. In un file che nominiamo style.css, definiamo l'aspetto degli elementi HTML:

@font-face {
	font-family: 'ubuntu';
	src: url('../fonts/Ubuntu.woff') format('woff');
}
html, body{
	font-size: 100%;
}
#logo{
	overflow: hidden;
	width: 100%;
	margin: 1em auto;
	text-align: center;
}
#cartello {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	padding: .2em .8em;
	width: 33%;
	float: left;
}
#site-title{
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	padding: .2em .8em;
	width: 67%;
	float: left;
	font-family: ubuntu, Arial, sans-serif;
	font-size: 6.6rem;
	font-weight: bold;
	text-transform: uppercase;
}

Concentriamoci sul container dell'immagine. Per facilitare il calcolo delle dimensioni, abbiamo assegnato alla proprietà box-sizing il valore border-box. In questo modo, la larghezza dell'elemento sarà calcolata sul bordo della div, e comprenderà sia il padding che i bordi (maggiori info su box sizing).

Abbiamo, quindi, assegnato all'elemento object una larghezza pari al 33% rispetto al suo container, l'elemento header. L'altezza, invece, viene calcolata in automatico in base alle proporzioni dell'immagine SVG.

Le media query

Dato che sono diverse le viewport dei due documenti, le media query con cui controlleremo le dimensioni dell'immagine SVG saranno distinte da quelle relative al documento HTML. Cominciamo dal controllo degli elementi HTML, e aggiungiamo le seguenti media query nel foglio di stile style.css:

@media screen and (max-){
	#site-title{ font-size: 2.8rem; }
}
@media screen and (min-) and (max-){
	#site-title{ font-size: 3.6rem; }
}
@media screen and (min-){
	#site-title{ font-size: 6.4rem; }
}

Creiamo, poi, un nuovo foglio di stile, nominiamolo svg.css, e inseriamo al suo interno la seguente media query:

@media screen and (max-){
	#cartello-superiore{ display: none; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: none; }
}

Il primo break point è impostato a 180px (un terzo circa di 540px). Qualora la viewport dell'immagine SVG, ossia la larghezza dell'elemento object, sia inferiore a 180px, gli elementi g#cartello-superiore e g#cartello-inferiore non saranno visualizzati.

L'elemento dell'immagine originale visibile su viewport inferiori ai 180px

Cartello a dimensioni ridotte

Impostiamo, quindi, un secondo break point:

@media screen and (min-) and (max-){
	#cartello-superiore{ display: block; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: none; }
}

Qualora la larghezza del container sia compresa tra 181 e 338 pixel, sarà visualizzato anche il cartello superiore.

Il cartello posteriore appare su Opera Mobile per Android in modalità landscape

Cartello su Opera Mobile

Infine, impostiamo l'ultimo break point per gli schermi di dimensioni superiori:

@media screen and (min-){
	#cartello-superiore{ display: block; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: block; }
}

In questo caso vengono visualizzati tutti gli elementi che compongono l'immagine.

L'immagine SVG completa su Safari per OS-X

Cartello su Safari

Il controllo del viewBox

Il rettangolo grigio che si nota in alcune immagini qui sopra individua l'elemento object. Esso mantiene sempre le stesse proporzioni, stabilite dal valore dell'attributo viewBox dell'elemento svg.

Ciò non genera problemi quando le dimensioni dello schermo permettono di visualizzare l'intera immagine. Sugli schermi di dimensioni inferiori, le proporzioni stabilite dal viewBox rimangono sempre costanti, ma la parte inferiore dell'immagine non sarà visibile, lasciando uno spazio vuoto al posto del cartello inferiore.

Purtroppo, non esiste una proprietà CSS che permetta di controllare il viewBox con le media query, quindi non esiste un modo diretto di risolvere il problema. Tra le possibili soluzioni, si può pensare di controllare le dimensioni del container e incorporare l'immagine SVG come background.

L'elemento svg rimane lo stesso:

<svg
	...
	width="100%"
	viewBox="-1 0 121.97654 180.21942"
	... >

Nel documento HTML andremo a sostituire l'elemento object con un div:

<header id="logo">
	<div id="cartello"></div>
	<h1 id="site-title">Australia road signs</h1>
</header>

Nel foglio di stile principale, assegniamo il seguente blocco di dicharazioni a div#cartello:

#cartello {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	padding: .2em .8em;
	float: left;
	background: #e9e9e9 url(../cartello.svg) center top no-repeat;
	background-size: cover;
}

La proprietà background-size ci permette di visualizzare l'immagine SVG nella sua interezza.

Non rimane che definire le media query per il documento HTML e per l'immagine SVG. Nel foglio di stile principale aggiungiamo:

@media screen and (max-){
	#site-title{
		font-size: 2.8rem;
	}
	#cartello{
		width: 33vw;
		height: 33vw;
	}
}
@media screen and (min-) and (max-){
	#site-title{
		font-size: 3.6rem;
	}
	#cartello{
		width: 33vw;
		height: 33vw;
	}
}
@media screen and (min-){
	#site-title{
		font-size: 6.4rem;
	}
	#cartello{
		width: 33vw;
		height: 48.777vw;
	}
}

Oltre a definire le dimensioni del font, sono state definite le dimensioni, in altezza e larghezza, della div#cartello. L'unità di misura utilizzata vw (viewport height) permette di assegnare agli elementi dimensioni proporzionate alla larghezza della viewport.

Il supporto delle viewport unit (fonte caniuse)

Caniuse viewport units

Conoscendo le proporzioni dell'immagine, si può stabilire lo stesso rapporto tra altezza e larghezza del div#cartello. Le due media query iniziali stabiliscono un rapporto di 1 a 1: width: 33vw; height: 33vw. L'ultima media query stabilisce un rapporto uguale a quello stabilito dall'attributo viewBox dell'immagine: width: 33vw; height: 48.777vw.

Prima di dichiarare le ultime istruzioni CSS, è bene ricordare che, per motivi di sicurezza, i file SVG incorporati come immagini non possono includere risorse esterne. Pertanto le media query riferite all'immagine SVG dovranno essere dichiarate nello stesso documento. Nel file cartello.svg, dopo l'elemento svg, dovremo aggiungere le seguenti media query:

<style>
<![CDATA[
@media screen and (max-){
	#cartello-superiore{ display: none; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: none; }
}
@media screen and (min-) and (max-){
	#cartello-superiore{ display: block; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: none; }
}
@media screen and (min-){
	#cartello-superiore{ display: block; }
	#canguro{ display: block; }
	#cartello-inferiore{ display: block; }
}
]]>
</style>

Ora l'immagine ed il suo container hanno le stesse dimensioni qualunque sia la risoluzione dello schermo.

L'immagine SVG si adatta perfettamente al suo container di colore grigio

SVG responsive

Riferimenti

Ti consigliamo anche