Διορθώστε το κιτ για κινητά 100vh

Ο χειρισμός του Mobile Webkit των 100vh ίσως χρειαστεί περισσότερη προσοχή

Έχω προβλήματα

Ενώ απολάμβανα αυτήν την πολύ διαδικτυακή εφαρμογή μου, έχω παρατηρήσει πάντα ότι το περιεχόμενο στο πάνω μέρος στο κινητό σαφάρι ήταν κάπως σπασμένο. Εάν φορτώσετε ξανά τη σελίδα, θα δείτε ότι το πρώτο περιεχόμενο που φορτώνεται για κάθε ανάρτηση ιστολογίου περιέχει τα ακόλουθα στοιχεία:

  • Τίτλος της θέσης
  • Υπότιτλος με σύντομη περιγραφή
  • Υποσέλιδο με συγγραφέα, κατηγορία & ημερομηνία

Αυτό το υποσέλιδο προορίζεται να είναι πάντα ορατό στο κάτω μέρος της θύρας προβολής κατά τη φόρτωση της σελίδας, μιμείται μια προβολή εξωφύλλου που μοιάζει με περιοδικό. Φαίνεται ωραίο, μεταδίδει ένα σαφές μήνυμα (δηλαδή σχετικά με αυτό το άρθρο) και αποφεύγει τυχόν παραμορφώσεις. Όλος αυτός ο ήρωας υλοποιείται με έναν απλό τρόπο χρησιμοποιώντας το ύψος τιμής CSS: 100vh, χρησιμοποιώντας όλο το διαθέσιμο ύψος της οθόνης της συσκευής.

Όταν ο χρήστης κάνει κύλιση προς τα κάτω λίγο, αυτό το εξώφυλλο ήρωας ξεθωριάζει κάνοντας θέση για το πραγματικό περιεχόμενο. Το αστείο είναι ότι αυτό δεν λειτούργησε ποτέ στο iOS. Δείτε πώς έμοιαζε:

Image f1a30a30a13c

Όπως μπορείτε να δείτε, δεν υπάρχει ορατό υποσέλιδο. Στην πραγματικότητα, είναι κρυμμένο κάτω από την κάτω μπάρα του Safari.

Έχω μια λύση

Αφού έβαλα το καπέλο μου και ξεκίνησα έρευνα στον παγκόσμιο ιστό, ανακάλυψα σίγουρα μια λύση, καθώς άλλοι είχαν προηγουμένως αυτό το ζήτημα.

tl; dr: χρησιμοποιώντας το Webkit's -webkit-fill-available κάνει το κόλπο. Δείτε πώς φαίνεται:

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

Ωστόσο, χρησιμοποιώντας αυτό ως πρότυπο για τη λύση JSS μου δεν λειτούργησε 100%. Το ύψος μειώθηκε μόνο το εγγενές ύψος του δοχείου. Επομένως, πρέπει να εντοπίσω σε ποια συσκευή είμαι και να εφαρμόσω υπό όρους το σωστό στυλ.

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

Αυτό που απομένει τώρα είναι η υπό όρους χρήση:

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

Εφαρμόζοντας την παραπάνω επιδιόρθωση, όλα λειτουργούν τώρα όμορφα. Ευχαριστώ για την ανάγνωση! Πηγές για τις αναφερόμενες αρχικές δημοσιεύσεις παρακάτω στο προσάρτημα.

  • Tom

Προτάσεις

Σχετικά

Προσάρτημα

Γλώσσες