Responsive Images

MobileTech Conference, Berlin 04.09.2013

 

Sven Wolfermann | maddesigns

Wer ist die Flitzpiepe da überhaupt?

Sven Wolfermann - maddesigns

Twitter: @maddesigns
Web: http://maddesigns.de

Responsive Webdesign

flexible Medieninhalte

keine statische Breitenangaben

img, embed, object, video {
  max-width: 100%;
}

Für Medien muss im CSS eine flexible Breite gesetzt werden, die Höhe soll sich automatisch in Relation anpassen.


img, embed, object, video {
   max-width: 100%; /* max. width original px */
   height: auto;
/* width: auto; */
}

verschiedene Bildschirm-Größen

Statistik von cartoonized.net

Bilder größter Anteil bei Websites

Responsive Images

Größenübersicht deviceoptimierter Bilder

Asset Loading Tests von Tim Kadlec

Tests des Ladeverhalten mobiler Browser

Beispiel: Test CSS-Hintergrundbilder

<div class="test5"></div>
@media all and (min-width: 601px) {
  .test5 {
    background-image: url("img/test5-desktop.png");
  }
}
@media all and (max-width: 600px) {
  .test5 {
    background-image: url("img/test5-mobile.png");
  }
}

Asset Loading Tests von Tim Kadlec

nur das passende Bild wird geladen, gut!

Responsive Images

Eine einfache und gute Lösung meiner Meinung nach, ist die <noscript>-Lösung mit HTML5 data-Attributen

<noscript data-large="Koala-large.jpg"
          data-small="Koala-small.jpg"
          data-alt="Koala">
          <img src="Koala-small.jpg" alt="Koala" />
</noscript>

Vorteil: Assets die im <noscript>-Tag eingebunden sind, werden nicht vom Browser in den DOM eingefügt (und nicht geladen), wenn JavaScript aktiviert ist.

+ Ressourcen werden nicht doppelt geladen

− JavaScript notwendig

Responsive Images – <noscript>

jQuery Snippet

$('noscript[data-large][data-small]').each(function(){
  var $this = $(this);
  var src = screen.width >= 500 ?
            $this.data('large') : $this.data('small');

  $('<img src="' + src + '" alt="' + $this
  .data('alt') + '" />')
  .insertAfter($this);
});
<!-- small screen DOM -->
<noscript ... >
  <img src="Koala-small.jpg" alt="Koala" />
</noscript>
<img src="Koala-small.jpg" alt="Koala">

Adaptive Images

adaptive-images.com Script einbinden

Cookie-Snippet so früh wie möglich im <head>

<head>
 <script>
 document.cookie='resolution='+Math.max(screen.width,screen.height)+';
 path=/';
 </script>
 …
</head>

PHP-Script anpassen (global Breakpoints)

$resolutions = array(1382, 992, 768, 480, 320);

.htaccess anpassen

<IfModule mod_rewrite.c>
#Enable URL rewriting
RewriteEngine On

Options +FollowSymlinks
#Adaptive Images
#don't apply the AI behaviour to images inside AI's cache folder:
RewriteCond %{REQUEST_URI} !ai-cache
#further directories that shouldn't use AI
RewriteCond %{REQUEST_URI} !cssimages
#Send any GIF, JPG, or PNG request that IS NOT stored inside one of the above directories
RewriteRule ^.*\.(jpg|jpeg|png|gif)$ adaptive-images.php [L]
. . .

</IfModule>
            

Adaptive Images

Adaptive Images

Responsive Images Art Direction Usecase

<picture> Element

Aktuelle W3C-Diskussion – <picture> Element

Aufbau wie <video> Element

<picture width="500" height="500">
  <source src="large.jpg"  media="(min-width: 45em)">
  <source src="middle.jpg" media="(min-width: 18em)">
  <img src="small.jpg" alt="">
  <p>Accessible text</p>
</picture>

Picturefill

Polyfill für den <picture> Ansatz

<span data-picture data-alt="Alttext">
  <span data-src="small.jpg"></span>
  <span data-src="medium.jpg" data-media="(min-width:  400px)"></span>
  <span data-src="large.jpg"  data-media="(min-width:  800px)"></span>
  <span data-src="xlarge.jpg" data-media="(min-width: 1000px)"></span>

  <!-- Fallback content for non-JS browsers. Same img src as
  the initial, unqualified source element. -->
  <noscript>
    <img src="small.jpg" alt="Alt">
  </noscript>
</span>

jQuery Picture plugin

Markup wie <picture> Ansatz

$(function(){
    $('picture').picture();
});

oder <figure>

<figure class="responsive" alt="A Half Brained Idea"
        data-media="assets/images/small.png" 
        data-media440="assets/images/medium.png" 
        data-media600="assets/images/large.png">
  <noscript>
    <img src="assets/images/large.png" alt="A Half Brained Idea">
  </noscript>
</figure>

Vorschlag: srcset-Attribut

<img> durch ein neues Attribut erweitern, das mehrere Bildpfade und -qualitäten enthält

<img alt="The Breakfast Combo" 
     src="banner.jpeg"
     srcset="banner-HD.jpeg 2x, 
             banner-phone.jpeg 100w,
             banner-phone-HD.jpeg 100w 2x">

srcset-Polyfill

<picture> Element + srcset

Das beste aus beiden Vorschlägen

<picture width="500" height="500">
  <source media="(min-width: 45em)"
          srcset="large-1.jpg 1x, large-2.jpg 2x">
  <source media="(min-width: 18em)"
          srcset="med-1.jpg 1x, med-2.jpg 2x">
  <source srcset="small-1.jpg 1x, small-2.jpg 2x">
  <img src="small-1.jpg" alt="">
  <p>Accessible text</p>
</picture>

wird mit den Browserherstellern diskutiert, aktuell scheint die Integration vom "srcset"-Attribut voran getrieben zu werden

srcset Support in WebKit

Support für background-images in Safari 6, Chrome 21

background-image: -webkit-image-set(
  url(cloud-sd.png) 1x, url(cloud-hd.png) 2x);

Support für Pixel-Density in WebKit Nightly

<img src="normal-image.jpg" srcset="better-image.jpg 2x">

-› Retina-Support für iOS

Clown Car Technique

Media Queries innerhalb SVG

<img src="file.svg" alt="image">

Vorteil:
+ gut für Bild im Text

Nachteil:
− SVG erst ab Android 4, IE9
− Bild das erscheint, ist nicht das was man herunterladen kann
− Seitenverhältnis bleibt gleich

Clown Car Technique

file.svg

<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet">
 <title>Clown Car Technique</title>
 <style>
  svg { background-size: 100% 100%; background-repeat: no-repeat; }
 @media screen and (max-width: 400px) {
  svg {background-image: url(images/small.png);} }
 @media screen and (min-width: 401px) and (max-width: 700px) {
  svg {background-image: url(images/medium.png);} }
 @media screen and (min-width: 701px) and (max-width: 1000px) {
  svg {background-image: url(images/big.png);} }
 @media screen and (min-width: 1001px) {
  svg {background-image: url(images/huge.png);} }
 </style>
</svg> 

Responsive Images Service – ReSRC.it

Imager.js

BBC News Technik um Bilder dynamisch und responsive zu laden

<div class="delayed-image-load" 
     data-src="http://placehold.it/340" 
     data-width="340"></div>

RESTful Image URL:
http://your-image-service.com/horse/100/

Focal Point – Lösungsvarianten für Bildausschnitte

HiDPI screens aka „Retina“

„Retina“

doppelte Pixeldichte, iPhone = 326ppi

List of mobile phones with HD display

Rumor: Apple to double 'iPhone 5S' Retina resolution to 1.5M pixels

Android Screen Vielfalt


Samsung Android Screen Sizes:
2.8, 3.14, 3.2, 3.4, 3.5, 3.6, 3.65, 3.7, 3.97, 4, 4.2, 4.27, 4.3, 4.5, 4.52, 4.65, 4.8, 5, 5.3, 5.5, 5.8, 6.3, 7, 7.7, 8, 10, 10.1 (Tweet von @dkdsgn)

Problem „halbe“ Pixel

Pixel-Matching auf unterschiedlichen Android-Screens

kann visuelle „Fehler“ hervorrufen

„Retina“

Problem: hochgezogene Pixel

mehrere optimierte Grafiken müssen bereit gestellt werden

Lösung wäre „image-set()“

background-image: -webkit-image-set(
    url(cloud-sd.png) 1x, url(cloud-hd.png) 2x);

CSS Media Queries

CSS abhängig von der Pixeldichte

@media only screen and (-webkit-max-device-pixel-ratio: 0.75),
       only screen and (max-resolution: 90dpi) {
  /* LowDPI CSS */
}
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (min-resolution: 144dpi) {
  /* HiDPI CSS */
}
@media only screen and (-webkit-min-device-pixel-ratio: 2),
       only screen and (min-resolution: 192dpi) {
  /* Retina specific CSS */
}

Retina JPGs

Bildgröße: 400x400px
Qualität: 60
Größe: 49.161 Byte

Bildgröße: 800x800px
Qualität: 15
Größe: 51.289 Byte

<img width="400" src="normal.jpg" alt="">
<img width="400" src="retina.jpg" alt="">

SVG – Scalable Vector Graphic

optimal für Logos & Icons

<img src="img/SVG-logo.svg" width="100" alt="">
<img src="img/SVG-logo.svg" width="200" alt="">
<img src="img/SVG-logo.svg" width="300" alt="">
Safari 5 Bug: Höhe (height="") muss angegeben werden

SVG vs. PNG

 

SVG

7,57 KB

51,50 KB

4,50 KB

 

PNG 200px

6,50 KB

11,10 KB

4,18 KB

PNG 400px

11,80 KB

27,60 KB

8,32 KB

PNG 800px

18,50 KB

72,70 KB

14,80 KB

fett = PNG kleiner als SVG

die Datenmenge für kleine PNG-Bilder ist häufig geringer als eine SVG-Grafik

Classic CSS Sprites – Image-Requests sparen

SVG-Sprites

funktionieren wie normale Image-Sprites

.svg .cloud {
  background: url(img/SVG_sprites.svg);
}
.no-svg .cloud {
  background: url(img/SVG_sprites.png);
}
.cloud {
  background-position: 0px 0px;
}
.cloud-active {
  background-position: -64px 0px;
}

iconizr.com – SVG-Sprite-Service mit PNG-Fallback-Generierung

Icon-Fonts

Icon Fonts == Dingbats on dope

Vorteil:

Icon Fonts

kostenloser Service icomoon.io

Data URI

HTML

<img src="logo-maddesigns.png" alt="Logo maddesigns">

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE...">

CSS

<style>
  .logo { background-image: url("logo-maddesigns.png") }
</style>

<style>
  .logo { background-image: url("data:image/png;base64,iVBORw...")}
</style>

Data URI

Nachteile

Vorsicht mit großen Bildern – iOS Resource Limits

Bilder optimieren

Bildoptimierung kann Kosten sparen

Beispiel:
Amazon Web Service (AWS) – jedes gesparte Byte kann helfen Kosten zu sparen

Bildformat

das richtige Bildformat je Bildinhalt verwenden!

zusätzlich PNGs crushen!

JPG für Photos verwenden! -› JPEGmini

Online-Tool

WebP

kleinere Bilddaten bei vergleichbarer Qualität

nur Chrome (und Opera)

Problematisch: Facebook testete WebP-Bilder, User waren unzufrieden

Video und Slides zum WebP-Status

Weitere Online-Tools zur Bildkomprimierung

Mobilnetz Provider Kompression (Vodafone UK)

Caching

Apache Modul „Expires Header“ zum Caching verwenden

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css                 "access plus 1 week"
ExpiresByType application/javascript   "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType image/gif                "access plus 1 month"
ExpiresByType image/jpeg               "access plus 1 month"
ExpiresByType image/png                "access plus 1 month"
</IfModule>

weitere interessante Links

8 Guidelines and 1 Rule for Responsive Images

Sensible jumps in responsive image file sizes

Responsive Images for Ruby on Rails

Riloadr – cross-browser framework-independent responsive images loader

Squeezr – Device-aware Adaptive Images and more

Adept JPG Compressor

Grunt Responsive Images

Responsive Images with Apropos (Compass Plugin)

Danke für die Aufmerksamkeit!

Sven Wolfermann | maddesigns

 

http://maddesigns.de/responsive-images/