mitmario.dev

Mobile First und der Viewport

CSS Im Browser 4 Min Lesezeit 3 BeispieleLektion 1 von 7

Ein Kasten mit width: 480px ragt auf einem Handy, das 380 Pixel breit ist, aus dem Bild, und die ganze Seite lässt sich seitwärts schieben. Ohne diese eine Breite wäre nichts passiert.

Inhalt ist von Natur aus responsiv

Ein Absatz ohne jedes CSS passt sich jeder Breite an. Er bricht um, wo er umbrechen muss, und ist auf einem 320px schmalen Handy genauso lesbar wie auf einem breiten Bildschirm. Mit Überschriften, Listen und Tabellen ist es dasselbe.

Kaputt macht ihn erst festes CSS. Eine Breite in Pixeln etwa, eine Höhe oder ein Innenabstand, der auf 400px mehr Platz frisst, als übrig ist.

Bei einem Layout-Problem auf schmalen Geräten frage ich deshalb nicht, wie ich das responsiv mache. Ich frage, welche meiner Angaben es kaputt gemacht hat. Meistens ist es ein width.

Die eine Zeile im head

Ohne Viewport-Meta
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="UTF-8">
    <title>Ohne Viewport</title>
    <style>
      body {
        margin: 0;
        padding: 16px;
        font-family: system-ui, sans-serif;
        line-height: 1.5;
      }

      h1 {
        font-size: 28px;
      }
    </style>
  </head>
  <body>
    <h1>Ohne Viewport-Meta</h1>
    <p>Ein Handy tut ohne diese eine Zeile so, als wäre es 980
    Pixel breit, und zoomt die fertige Seite dann heraus. Alles
    wird winzig, und die Media Queries greifen bei den falschen
    Breiten.</p>
    <p>Hier siehst du den Unterschied nicht: Im Rahmen übergeht
    jeder Browser die Zeile, auch der auf dem Handy. Als eigene
    Seite ist er dort drastisch.</p>
  </body>
</html>
Mit Viewport-Meta
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Mit Viewport</title>
    <style>
      body {
        margin: 0;
        padding: 16px;
        font-family: system-ui, sans-serif;
        line-height: 1.5;
      }

      h1 {
        font-size: 28px;
      }
    </style>
  </head>
  <body>
    <h1>Mit Viewport-Meta</h1>
    <p>width=device-width heißt: nimm die echte Breite des Geräts.
    initial-scale=1 heißt: zoom beim Laden nicht.</p>
    <p>Diese eine Zeile gehört in jedes HTML-Dokument, das du je
    schreibst. Sie steht seit dem HTML-Kurs in deinem Grundgerüst,
    und hier steht endlich, warum.</p>
  </body>
</html>

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

Ohne diese Zeile tut ein Handy so, als wäre es 980 Pixel breit, rendert die Seite in dieser Breite und zoomt das Ergebnis danach heraus, bis es auf den Bildschirm passt. Der Text ist winzig, du musst alles vergrößern, und deine Media Queries greifen bei den falschen Breiten, weil der Browser eine erfundene Breite meldet.

Das hat einen historischen Grund. Als 2007 das iPhone kam, war kaum eine Seite für so einen schmalen Bildschirm gebaut. Die Wahl stand zwischen “alles ist kaputt” und “alles ist klein”, und die Hersteller entschieden sich fürs Kleine. Dabei ist es bis heute geblieben.

width=device-width sagt dem Browser, dass er die echte Breite nehmen soll, initial-scale=1, dass er beim Laden nicht zoomt. Beides zusammen gehört in jedes Dokument.

Gelegentlich findet man dort noch maximum-scale=1 und user-scalable=no, und die schreibe ich nie. Sie verbieten dem Nutzer das Zoomen. Für Menschen, die schlecht sehen, ist die Seite damit unbrauchbar gemacht, nur um ein Layout-Problem zu verstecken.

Die beiden Beispiele oben unterscheiden sich in dieser einen Zeile, und hier sehen sie trotzdem gleich aus. Im Inspector misst die Überschrift in beiden 348 × 42 bei font-size: 28px, der body beide Male rund 380 × 336. Die Zeile wirkt nur, wenn ein Handy die Datei als ganze Seite öffnet. Die Beispiele hier laufen in einem Rahmen, und in einem Rahmen übergeht jeder Browser sie, auch der auf deinem Handy. Am Rechner kommt dazu, dass ein Desktop-Browser sie ohnehin nicht beachtet. Sichtbar wird der Unterschied erst, wenn der Code als eigene Seite läuft, etwa als gespeicherte Datei in Chrome. Dort schaltet in den Entwicklerwerkzeugen Strg+Umschalt+M (auf dem Mac Cmd+Umschalt+M) die Geräteansicht ein, und oben lässt sich ein Handy auswählen. Auf dem Handy selbst geht es auch. Weglassen darfst du die Zeile trotzdem nirgends.

Mobile First heißt hinzufügen, nicht wegnehmen

Feste Breite gegen mitwachsende
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 16px;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
  background-color: #f4f4f5;
}

.titel {
  margin-bottom: 4px;
  font-size: 14px;
  color: #52525b;
}

.karte {
  margin-bottom: 16px;
  padding: 16px;
  border-radius: 12px;
  background-color: #ffffff;
}

.karte p {
  margin: 0;
}

/* Eine feste Breite kennt den Bildschirm nicht,
   auf dem sie landet. */
.fest {
  width: 480px;
}

/* Eine Höchstbreite ist eine Obergrenze und keine
   Zusage. Darunter passt sie sich an. */
.flexibel {
  max-width: 480px;
}

Mobile First bedeutet, dass die Regeln ohne Media Query für das kleinste Gerät gelten. Media Queries kommen erst ab einer Mindestbreite dazu und fügen etwas hinzu.

Deshalb ist min-width die Standardrichtung und nicht max-width. Der Unterschied liegt im Vorgehen.

  • Von klein nach groß schreibst du erst das Einfache (eine Spalte, alles untereinander) und ergänzt dann, was auf mehr Platz möglich wird.
  • Von groß nach klein schreibst du erst das Komplizierte und nimmst danach Stück für Stück Dinge zurück. Dabei vergisst man leicht eines, und dann ragt auf dem Handy irgendetwas heraus.

Der zweite Grund ist praktischer. Die einfache Fassung ist die, die immer funktioniert. Hat deine Media Query einen Tippfehler, sieht die Seite auf dem Desktop eben aus wie auf dem Handy. Andersherum wäre sie auf dem Handy unbenutzbar.

Woran es dabei oft hängt, ist width, und gemeint ist fast immer max-width. Eine Obergrenze statt einer Zusage.

Im dritten Beispiel stehen die beiden nebeneinander, und im Streifen sieht man, was passiert. Der obere Kasten trägt width: 480px und misst 480 × 80, obwohl die Seite daneben nur 380 Pixel breit ist. Er ist also breiter als die Seite, auf der er steht, und der Scrollbalken darunter gehört ihm. Der untere trägt max-width: 480px, misst 348 × 104 und hört dort auf, wo die Seite aufhört. Dafür ist er eine Zeile höher, denn sein Text braucht bei weniger Breite mehr Platz nach unten.

In der Aufgabe fällt eine Seite auf 400 Pixeln auseinander.

Zum Mitnehmen

Ohne die Viewport-Zeile im head bekommt ein Handy eine Seite für 980 Pixel, nur verkleinert. Bei Mobile First steht das Schmale ohne Bedingung da, und min-width legt das Breite dazu. Wo width steht, ist fast immer max-width gemeint.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.