Ripari moveblan retejon 100vh

La uzado de 100vh de Mobile Webkit eble bezonos pli da atento

Mi havas problemojn

Dum mi ĝuis ĉi tiun retejan programon, mi ĉiam rimarkis, ke la enhavo super la faldita poŝtelefona safaro iom rompiĝis. Se vi reŝargas la paĝon, vi vidos, ke la unua enhavo ŝarĝita por ĉiu blogaĵo enhavas la jenajn erojn:

  • Titolo de la afiŝo
  • Subteksto kun mallonga priskribo
  • Piedo kun aŭtoro, kategorio kaj dato

Ĉi tiu piedlinio celas esti ĉiam videbla ĉe la fundo de vidpunkto post la ŝarĝo de la paĝo, imitante magazen-similan kovrilan vidon. Ĝi aspektas bele, komunikas klaran mesaĝon (t.e. pri kio temas ĉi tiu afiŝo) kaj evitas iajn deklinojn. Ĉi tiu tuta heroo estas efektivigita laŭ simpla maniero uzante la CSS-valoran altecon: 100vh, uzante ĉiun disponeblan altecon de la ekrano de la aparato.

Kiam la uzanto iomete rulumas, ĉi tiu heroa kovrilo malaperas, farante lokon al la efektiva enhavo. Amuza afero estas, ke ĉi tio neniam funkciis en iOS. Jen kiel ĝi aspektis:

Image f1a30a30a13c

Kiel vi povas vidi, neniu piedlinio videblas. Fakte ĝi estas kaŝita sub la suba stango de Safaro.

Mi havas solvon

Post surmeti mian ŝerokan ĉapelon kaj komenci enketon en la monda reto, mi certe malkovris solvon, ĉar aliaj antaŭe havis ĉi tiun problemon.

tl; dr: uzi Webkit -webkit-fill-available faras la artifikon. Jen kiel ĝi aspektas:

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

Tamen uzi ĉi tion kiel ŝablonon por mia JSS-solvo ne sukcesis 100%. La alteco nur reduktiĝis la interna alto de la ujo. Tial mi devas eltrovi sur kiu aparato mi estas kaj kondiĉe apliki la ĝustan stiladon.

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

Restas nun la kondiĉa uzado:

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

Aplikante la solvon supre, ĉio funkcias nun bone. Dankon pro la legado! Fontoj por la menciitaj originalaj afiŝoj sube en la aldono.

  • Tom