إصلاح webkit 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