Исправить мобильный webkit 100vh

Обработка 100vh в Mobile Webkit может потребовать большего внимания

У меня проблемы

Наслаждаясь этим самым моим веб-приложением, я всегда замечал, что контент в верхней части мобильного сафари был несколько неработоспособным. Если вы перезагрузите страницу, вы увидите, что первый контент, загружаемый для каждого сообщения в блоге, содержит следующие элементы:

  • Заголовок сообщения
  • Подзаголовок с кратким описанием
  • Нижний колонтитул с автором, категорией и датой

Этот нижний колонтитул должен всегда быть видимым внизу окна просмотра при загрузке страницы, имитируя вид обложки журнала. Он выглядит красиво, передает четкое сообщение (то есть о чем этот пост) и избегает каких-либо отклонений. Весь этот герой реализован простым способом с использованием CSS-значения height: 100vh, используя всю доступную высоту экрана устройства.

Когда пользователь прокручивает немного вниз, эта обложка героя исчезает, освобождая место для фактического контента. Забавно, но это никогда не работало на iOS. Вот как это выглядело:

Image f1a30a30a13c

Как видите, нижнего колонтитула не видно. Фактически, он скрыт под нижней панелью Safari.

У меня есть решение

После того, как я надел шляпу шерлока и начал расследование во всемирной паутине, я, несомненно, нашел решение, поскольку у других была эта проблема раньше.

tl; dr: использование Webkit -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

Предложения

Связанные

Приложение

Языки