Mobiles Webkit 100vh reparierenv

Die Handhabung von 100vh durch das mobile Webkit erfordert möglicherweise mehr Aufmerksamkeit

Ich habe Probleme

Während ich diese Web-App von mir genossen habe, ist mir immer aufgefallen, dass der Inhalt auf mobilen Safaris etwas kaputt war. Wenn Sie die Seite neu laden, sehen Sie, dass der erste Inhalt, der für jeden Blogbeitrag geladen wird, die folgenden Elemente enthält:

  • Titel des Beitrags
  • Untertitel mit kurzer Beschreibung
  • Fußzeile mit Autor, Kategorie & Datum

Diese Fußzeile soll beim Laden der Seite immer unten im Ansichtsfenster sichtbar sein und eine magazinartige Titelansicht imitieren. Es sieht gut aus, kommuniziert eine klare Botschaft (d.h. worum es in diesem Beitrag geht) und vermeidet Ablenkungen. Dieser ganze Held wird auf einfache Weise implementiert, indem der CSS-Wert height: 100vh verwendet wird, wobei die gesamte verfügbare Höhe des Bildschirms des Geräts verwendet wird.

Wenn der Benutzer ein wenig nach unten scrollt, verschwindet dieses Helden-Cover und macht Platz für den eigentlichen Inhalt. Komisch ist, dass dies unter iOS nie funktioniert hat. So sah es aus:

Image f1a30a30a13c

Wie Sie sehen, ist keine Fußzeile sichtbar. Tatsächlich ist es unter der unteren Leiste von Safari versteckt.

Ich habe eine Lösung

Nachdem ich meinen Sherlock-Hut aufgesetzt und eine Recherche im World Wide Web gestartet habe, habe ich sicherlich eine Lösung gefunden, da andere dieses Problem schon einmal hatten.

tl;dr: Die Verwendung von -webkit-fill-available von Webkit reicht aus. So sieht es aus:

.hero-container {
  min-height: 100vh;
  /* fix for mobile webkit */
  min-height: -webkit-fill-available;
}

Dies als Vorlage für meine JSS-Lösung zu verwenden, hat jedoch nicht zu 100% geklappt. Die Höhe wurde nur auf die Eigenhöhe des Containers reduziert. Daher muss ich erkennen, auf welchem Gerät ich mich befinde und bedingt das richtige Styling anwenden.

/**
 * Check if current session runs in
 * a mobile webkit instance.
 */
export function isMobileWebkit() {
  const ua = window.navigator.userAgent;
  const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
  const webkit = !!ua.match(/WebKit/i);
  return iOS && webkit && !ua.match(/CriOS/i);
}

/**
 * As I'm using Next.js, window is undefined
 * on the server, therefore we need to call
 * 'isMobileWebkit' after mounting.
 */
export function useIsMobileWebkit() {
  const [flag, setFlag] = useState(false);

  useEffect(() => setFlag(isMobileWebkit()), []);

  return flag;
}

Was jetzt noch übrig ist, ist die bedingte Verwendung:

// We're using 'clsx' for classname merging.
import clsx from "clsx";

function Hero(){
  const classes = useStyles();
  
  return (
    <div
      className={clsx(classes.hero, {
        [classes.heroCssWebkitFix]: isMobileWebKit,
      })}>
      ...
      </div>
  );
}

// ... slice of the styling:

const useStyles = makeStyles(theme => ({
  hero: {
    minHeight: "100vh",
    width: "100%",
    display: "flex",
    flexDirection: "column",
    alignItems: "stretch",
    paddingBottom: theme.spacing(2),
    paddingTop: theme.spacing(2),
  },
  heroCssWebkitFix: {
    // mobile viewport bug fix
    minHeight: "-webkit-fill-available",
    paddingBottom: 0,
  },
}))

Wenn Sie den obigen Fix anwenden, funktioniert jetzt alles gut. Danke fürs Lesen! Quellen für die genannten Originalbeiträge unten im Nachtrag.

  • Tom