HTML5, CSS3, JavaScript WB@HCJ

Responsive Web Design

[Chicken & Thoreau]

Well established hierarchies are not easily uprooted; Closely held beliefs are not easily released; So ritual enthralls generation after generation.

Tao Te Ching; 38 Ritual

Słowa „responsive” użył po raz pierwszy Ethan Marcotte w artykule Responsive Web Design/ opublikowanym na A List Apart. Składniki „responsive design”:

  1. A flexible, grid-based layout.
  2. Flexible images and media.
  3. Media queries, a module from the CSS3 specification.

Lektura:

Rozszerzenia do przeglądarek:

Użyteczne rzeczy:

Wtyczki jQuery:

Responsive Web pages, przykłady:

[This is the Web]

[Źródło]

Uwaga: W kodzie poniżej usunięto wszystkie odległości pionowe. Dlaczego? Ponieważ w „responsive design” istotne są tylko „szerokości”.

Fixed layout

Zaczynamy od prostego szablonu:

Nie jest to co prawda „czysty” HTML5, ale za to ma sensowny outline (schemat):

<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  ...
</head>
<body>
<div id="wrapper">
  <header id="header">
    <!-- nav is a sectioning element and needs a title heading -->
    <div id="navigation">
      <ul>
        <li><a href="#">Morskiego Oka</a></li>
        ...
      </ul>
    </div>
  </header>
  <div id="content">
    <h1>Doliny Tarzańskie</h1>
    <p>Article content…</p>
    <h2>Morskie Oko</h2>
    <p>Article content…</p>
    ...
  </div>
  <aside id="sidebar">
    <h1>Sidebar heading</h1>
    <p>Content…</p>
  </aside>
  <footer id="footer">
    <p>Content… (footer is not sectioning element)</p>
  </footer>
</div>
</body>
</html>

Szerokości elementów na tej stronie są takie (main.css):

#wrapper { width: 960px;    margin: 0 auto; }
#header  { width: 940px; }
#sidebar { width: 220px; }
#content { width: 700px; }
#footer  { width: 940px; }

Dlaczego w szablonie nie użyto elementu article i jaki problematyczny outline miałby szablon korzystający z elementów article, section opisano tutaj:

Strona ta na „małych urządzeniach” jest nieczytelna ponieważ jest auto resized.

Po zablokowaniu auto resizing strona wyświetla się tak:

Jak blokujemy automatyczne przeskalowywanie? Tak:

<meta name="viewport" content="initial-scale=1.0,width=device-width">

albo zmieniamy wartość współczynnika initial-scale, na przykład:

<meta name="viewport" content="initial-scale=0.5,width=device-width">
<meta name="viewport" content="initial-scale=2.0,width=device-width">

Co dają takie zmiany? Jak to zapisać?

Media queries

Jak? Może tak:

<link rel="stylesheet" media="screen"
     href="screen.css">
<link rel="stylesheet" media="screen and (orientation: portrait)"
     href="portrait-screen.css">
<link rel="stylesheet" media="not screen and (orientation: portrait)"
     href="portrait-screen.css">
<link rel="stylesheet" media="screen and (orientation: portrait) and (min-width: 800px)"
     href="800wide-portrait-screen.css">

albo może wszystko zapiszemy w jednym pliku:

@media screen and (orientation: portrait) {
  ... CSS ...
}
/*    (not (screen and (orientation: portrait))) */
@media not screen and (orientation: portrait) {
  ... CSS ...
}
@media screen and (orientation: portrait) and (min-width: 800px) {
  ... CSS ...
}

(ostatni przykład: „the viewport is 800px wide or wider”)

Viewport – widths

width=device-width oznacza: css pixels = device pixels, A pixel is not a pixel is not a pixel:

<meta name="viewport" content="initial-scale=1.0,width=device-width">

iPad?

@media screen and (max-width: 768px) {
  #wrapper, #header, #footer, #navigation {
    width: 768px;
    margin: 0px;
  }
  #navigation {
    text-align: center;
  }
  #navigation ul li a {
    line-height: 40px;
    font-size: 30px;
  }
  #content, #sidebar {
    padding-right: 10px;
    padding-left: 10px;
    width: 728px;
  }
}

Zamieniona kolejność elementów sidebar i footer.

Fluid layout

Rachunki poniżej będą łatwiejsze do ogarnięcia z widokiem DOM szablonu strony:

DOM of the html5 template

Same media queries to za mało…

Użyty CSS daje taką „nieciągłość” – przy zmianie szerokości strony (i równocześnie szerokości viewport) w momencie, kiedy cała strona nie mieści się w oknie przeglądarki pojawia się pasek przesuwania.

Zlikwidujemy pojawiania się paska przeliczając wymiary poziome na procenty (tzw. fluid layout, ?tłum – procentowy). W tym celu zastosujemy wzór Marcotta:

target  ÷  context  =  result

W naszym przykładzie kontekst, to najbardziej zewnętrzny div:

#wrapper {
  margin: 0 auto;
  width: 960px;
}

zmieniamy wymiar poziomy:

#wrapper {
  margin: 0 auto;
  width: 96%;
}

Oczywiście mogliśmy ustawić width na 100%. Ale „na oko” wybrałem 96% co daje mały ładny lewy i prawy margines.

Dalsze przeliczenia ze wzoru Marcotta (z użytego w przykładach CSS usunięto wszystkie deklaracje nie związane z szerokościami elementów):

#header {
  /* margin-right: 10px; */
  /* margin-left: 10px; */
  margin-right: 1.0416667%; /* 10 ÷ 960 */
  margin-left: 1.0416667%; /* 10 ÷ 960 */
  /* width: 940px; */
  width: 97.9166667%; /* 940 ÷ 960 */;
}
#navigation {
  /* margin-left: 10px; */
  margin-left: 1.0416667%; /* 10 ÷ 960 */
  /* padding-right: 10px; */
  /* padding-left: 10px; */
  padding-right: 1.0416667%; /* 10 ÷ 960 */
  padding-left: 1.0416667%; /* 10 ÷ 960 */
  width: 97.9166667%; /* 940 ÷ 960 */;
}
#navigation ul li {
  display: inline-block;
  margin-right: 2.6595745%; /* 25 ÷ 940 */
}
#navigation ul li a {
  /* margin-right: 25px; */
  /* przeniesione do reguły powyżej */
  /* margin-right: 2.6595745%; /\* 25 ÷ 940 *\/ */
}
#content {
  /* margin-right: 10px; */
  margin-right: 1.0416667%; /* 10 ÷ 960 */
  /* width: 700px; */
  width: 72.9166667%; /* 700 ÷ 960 */
}
#sidebar {
  /* margin-left: 10px; */
  margin-left: 1.0416667%; /* 10 ÷ 960 */
  /* width: 220px; */
  width: 22.9166667%; /* 200 ÷ 960 */
}
#footer {
  /* margin-right: 10px; */
  margin-right: 1.0416667%; /* 10 ÷ 960 */
  margin-left: 1.0416667%; /* 10 ÷ 960 */
  /* width: 940px; */
  width: 97.9166667%; /* 940 ÷ 960 */;
}

Przy przejściu na szerokość mniejszą od 768px korzystamy z media query:

@media screen and (max-width: 768px) {
  #header, #content, #sidebar, #footer {
    width: 100%;
    margin: 0px;
  }
}

Strona i źródło strony:

Fluid images

CSS:

img {
  max-width: 100%;
}

@media screen and (max-width: 768px) {
  #sidebar img {
    max-width: 50%;
    float: left;
    display: block;
  }
}

Fluid typography: fonts

Oznacza to że będziemy stosować jednostki em a nie px.

Wszystkie przeglądarki mają ustawioną domyślną wielkość fontu na 16px. Ale rachunki są łatwiejsze dla wartości 10px:

body {
  font-size: 62.5%; /* zmieniamy domyślny rozmiar fontu na 10px */
}

Jak zostało wyliczone 62.5%:

target ÷ context = result
10px   ÷ 16px    = 0.625

Teraz zamiast rachunków z 16px:

#navigation ul li a {
  /* font-size: 20px; */
  font-size: 1.25em;  /* 20px ÷ 16px */
}

będą prostsze rachunki z 10px:

#navigation ul li a {
  /* font-size: 20px; */
  font-size: 2em;  /* 20px ÷ 10px */
}

Podmienianie obrazków