Réparer le kit web mobile 100vh

La gestion de 100vh par Mobile Webkit pourrait nécessiter plus d'attention

j'ai des problèmes

Tout en profitant de cette application très Web, j'ai toujours remarqué que le contenu au-dessus de la ligne de flottaison sur le safari mobile était quelque peu cassé. Si vous rechargez la page, vous verrez que le premier contenu chargé pour chaque article de blog contient les éléments suivants :

  • Titre du poste
  • Sous-titre avec une courte description
  • Pied de page avec auteur, catégorie et date

Ce pied de page est destiné à être toujours visible en bas de la fenêtre lors du chargement de la page, imitant une vue de couverture de type magazine. Il est joli, communique un message clair (c'est-à-dire de quoi parle ce message) et évite toute déviation. Tout ce héros est implémenté de manière simple en utilisant la hauteur de la valeur CSS : 100vh, en utilisant toute la hauteur disponible de l'écran de l'appareil.

Lorsque l'utilisateur fait défiler un peu vers le bas, cette couverture de héros disparaît pour faire place au contenu réel. Ce qui est amusant, c'est que cela n'a jamais fonctionné sur iOS. Voici à quoi cela ressemblait :

Image f1a30a30a13c

Comme vous pouvez le voir, aucun pied de page n'est visible. En fait, il est caché sous la barre inférieure de Safari.

j'ai une solution

Après avoir mis mon chapeau de sherlock et commencé une enquête sur le World Wide Web, j'ai sûrement découvert une solution car d'autres ont déjà eu ce problème.

tl;dr : utiliser -webkit-fill-available de Webkit fait l'affaire. Voici à quoi cela ressemble :

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

Pourtant, l'utiliser comme modèle pour ma solution JSS n'a pas fonctionné à 100%. La hauteur n'a fait que réduire la hauteur intrinsèque du conteneur. Par conséquent, je dois détecter sur quel appareil je suis et appliquer sous certaines conditions le style correct.

/**
 * 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;
}

Il ne reste plus que l'utilisation conditionnelle :

// 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,
  },
}))

En appliquant le correctif ci-dessus, tout fonctionne maintenant correctement. Merci pour la lecture ! Sources pour les messages originaux mentionnés ci-dessous dans l'addendum.

  • Tom