Fix mobiele webkit 100vh

Mobile Webkit se hantering van 100vh sal dalk meer aandag moet kry

Ek het probleme

Terwyl ek van hierdie webprogram van my geniet het, het ek altyd opgemerk dat die inhoud bo-op die vou op mobiele safari ietwat gebreek was. As u die bladsy herlaai, sal u sien dat die eerste inhoud wat vir elke blogpos gelaai is, die volgende items bevat:

  • Titel van die berig
  • Ondertitel met 'n kort beskrywing
  • Voetskrif met outeur, kategorie en datum

Hierdie voetskrif is bedoel om altyd aan die onderkant van die uitsigpoort sigbaar te wees tydens die laai van die bladsy, wat 'n voorblad-agtige vooraansig naboots. Dit lyk mooi, kommunikeer 'n duidelike boodskap (dit wil sê waaroor hierdie berig gaan) en vermy buigings. Hierdie hele held word op 'n eenvoudige manier geïmplementeer deur die CSS-waardehoogte: 100vh te gebruik, met behulp van alle beskikbare hoogte van die toestel se skerm.

As die gebruiker 'n bietjie afblaai, vervaag hierdie heldeblad plek vir die werklike inhoud. Dit is egter snaaks dat dit nooit op iOS gewerk het nie. Hier is hoe dit gelyk het:

Image f1a30a30a13c

Soos u kan sien, is geen voetskrif sigbaar nie. In werklikheid is dit onder die onderste balk van Safari versteek.

Ek het 'n oplossing

Nadat ek my sherlock-hoed aangetrek het en 'n ondersoek op die wêreldwye webwerf begin het, het ek sekerlik 'n oplossing ontdek, aangesien ander dit al voorheen gehad het.

tl; dr: die gebruik van Webkit se -webkit-fill-available doen die truuk. Hier is hoe dit lyk:

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

Die gebruik daarvan as 'n sjabloon vir my JSS-oplossing het egter nie 100% gewerk nie. Die hoogte het net die intrinsieke hoogte van die houer verminder. Daarom moet ek opspoor op watter toestel ek gebruik en die regte styling voorwaardelik toepas.

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

Wat nou oorbly, is die voorwaardelike gebruik:

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

As u die oplossing hierbo toepas, werk alles nou mooi. Dankie vir die lees! Bronne vir die genoemde oorspronklike plasings hieronder in die addendum.

  • Tom