Correggi il webkit mobile 100vh

La gestione di 100vh da parte di Mobile Webkit potrebbe richiedere più attenzione

ho dei problemi

Mentre mi divertivo con questa mia app web, ho sempre notato che il contenuto above the fold su Mobile Safari era in qualche modo rotto. Se ricarichi la pagina, vedrai che il primo contenuto caricato per ogni post del blog contiene i seguenti elementi:

  • Titolo del post
  • Sottotitolo con una breve descrizione
  • Piè di pagina con autore, categoria e data

Questo piè di pagina deve essere sempre visibile nella parte inferiore del viewport al caricamento della pagina, imitando una vista di copertina simile a una rivista. Sembra carino, comunica un messaggio chiaro (cioè di cosa tratta questo post) ed evita qualsiasi deviazione. L'intero eroe viene implementato in modo semplice utilizzando l'altezza del valore CSS: 100vh, utilizzando tutta l'altezza disponibile dello schermo del dispositivo.

Quando l'utente scorre un po' verso il basso, questa copertina dell'eroe svanisce lasciando spazio al contenuto effettivo. La cosa divertente è che non ha mai funzionato su iOS. Ecco come appariva:

Image f1a30a30a13c

Come puoi vedere, nessun piè di pagina visibile. In effetti, è nascosto sotto la barra inferiore di Safari.

ho una soluzione

Dopo aver indossato il mio cappello da sherlock e aver avviato un'indagine nel world wide web, ho sicuramente scoperto una soluzione poiché altri hanno già avuto questo problema.

tl; dr: l'uso di -webkit-fill-available di Webkit fa il trucco. Ecco come appare:

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

Tuttavia, l'utilizzo di questo come modello per la mia soluzione JSS non ha funzionato al 100%. L'altezza è stata solo ridotta rispetto all'altezza intrinseca del contenitore. Pertanto, devo rilevare su quale dispositivo mi trovo e applicare in modo condizionale lo stile corretto.

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

Ciò che resta ora è l'uso condizionale:

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

Applicando la correzione sopra, ora tutto funziona bene. Grazie per la lettura! Fonti per i post originali menzionati di seguito nell'addendum.

  • Tom