CSS — отображать альтернативное изображение, когда оригинал не поддерживается

Я создаю веб-сайт и хочу использовать формат WebP для своих изображений. Я знаю, что не все браузеры поддерживают это, поэтому я хочу отображать альтернативное изображение JPG, если WebP не поддерживается. У меня есть div с этим классом, примененным к нему:

.my-class{
    background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.webp');
}

Я хочу добавить в этот класс что-то, что отображает альтернативу image.jpg, если веб-сайт используется в браузере, который не поддерживает WebP. Как этого добиться (с помощью чистого CSS)?


person Ameer Taweel    schedule 16.06.2019    source источник


Ответы (2)


Существует хорошее руководство о том, что вы хотите получить на CSS Tricks:

https://css-tricks.com/using-webp-images/

Чистый css не лучший способ решить эту проблему, вам нужно определить, поддерживает ли клиент webp, а css этого не сделает.

Поэтому вам нужен, например, Modenizr, чтобы определить, поддерживает ли клиент webp или нет.

https://modernizr.com/download?setclasses

После того, как вы выбрали то, что вам нужно (webp), вы получите небольшой файл js. Добавьте его на свою страницу, например:

<!DOCTYPE HTML>
 <html>
 <head>
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <script src="js/modernizr-custom.js"></script>
  </head>

Теперь в основном вы создадите свой класс следующим образом:

 .no-webp .elementWithBackgroundImage {
  background-image: url("image.jpg");
  }

 .webp .elementWithBackgroundImage{
  background-image: url("image.webp");
  }

Существует даже решение для клиентов, которые деактивировали js, но для этого нужен небольшой встроенный скрипт, который также можно найти в статье CSS Tricks.

Ваш класс будет выглядеть так:

.no-webp-my-class .elementWithBackgroundImage{
background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.jpg');
 }
.my-class .elementWithBackgroundImage{
background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.webp');
 }

Изменить

Есть еще один способ, но он требует некоторой работы и php. По сути, это не что иное, как переключатель браузера, и вам нужно заполнить свою таблицу стилей.

Чтобы упростить задачу, создайте файл с именем stylesheet.php или как-то так и объявите заголовок:

<?php 
  header("Content-type: text/css;charset=UTF-8"); 

чтобы сэкономить некоторую работу, эта душа прочитает существующий файл .css и выдаст его как эхо:

<?php 
  header("Content-type: text/css;charset=UTF-8"); 
  $file_read = fopen("stylesheet.css","r+");
    while(! feof($file_read))  {
    $css= fgets($file_read);
    echo "$css";
    }

Теперь все классы, использующие изображение webp, можно переключать, проверяя, не поддерживает ли браузер webp.

if( strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false ) {
// webp is supported!
 }
 else {
 // webp is not supported!
}

Что приведет к этому:

<?php 
  header("Content-type: text/css;charset=UTF-8"); 
  $file_read = fopen("stylesheet.css","r+");
    while(! feof($file_read))  {
    $css= fgets($file_read);
    echo "$css";
    }
if( strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false ) {
 echo "
 .my-class .elementWithBackgroundImage{
  background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.webp');
  }";

 }
 else {
 echo "
 .my-class {
  background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.jpg');
  }";
 }
 ?>

Изменить

Я кое-что забыл: вы можете добавить файл .php, как обычный файл .css, в свой html:

<link rel="stylesheet" type="text/css" href="stylesheet.php" media="screen"/>
person Thorsten Wolske    schedule 16.06.2019
comment
Это будет работать только для фоновых изображений. Лучше определить исходный набор для изображения в HTML, чтобы не ограничивать свойства стиля, которые можно применить. - person Claire; 16.06.2019
comment
Это был вопрос, и решение в html уже было дано в ответе перед моим, а также может быть найдено в статье о хитростях css. Но опять же ваше право ;) - person Thorsten Wolske; 16.06.2019
comment
Извините, я не хочу вас ругать. Ваш ответ, безусловно, не является неправильным, и я очень ценю, что вы оставили часть HTML и расширили остальную часть. Это правильный способ сделать это. - person Claire; 16.06.2019
comment
Все нормально, это сообщество или нет? ;) Мой английский уже не самый лучший, возможно, мое предложение было сформулировано немного резко. - person Thorsten Wolske; 16.06.2019
comment
Нисколько! Так держать! - person Claire; 17.06.2019
comment
Если бы это сработало, это было бы решением для меня. Проблема в том, что это не работает. Элемент, который должен иметь фон, вообще не показывает фона. Может быть причина в том, что я использую Vue.js, поэтому скрипт запускается перед скриптом Vue.js и ничего не появляется? - person Ameer Taweel; 17.06.2019
comment
Кто-то столкнулся с этой проблемой до: stackoverflow.com/questions/49221027/, решение похоже на webpack-modernizr-loader: github.com/itgalaxy/webpack-modernizr-loader. Но ваша мысль, пожалуй, верна. - person Thorsten Wolske; 17.06.2019
comment
@AmeerTaweel я добавил еще одно решение. - person Thorsten Wolske; 18.06.2019
comment
@ThorstenWolske Проблема в том, что в Vue.js вы вводите CSS внутри файла .vue. У вас есть идея, как заставить PHP прочитать это CSS? - person Ameer Taweel; 18.06.2019
comment
Моя первая мысль привела бы только к большему количеству работы. @AmeerTaweel, вы можете скопировать и вставить чистый CSS в файл stylesheet.php и добавить «ссылку» в HTML. - person Thorsten Wolske; 18.06.2019
comment
То есть это будет что-то вроде этого?: <?php $css= fgets($file_read); echo "$css"; if( strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false ) { echo ".my-class .elementWithBackgroundImage{ background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.webp'); }"; } else { echo ".my-class { background: linear-gradient(to right bottom, rgba(89, 167, 255, 0.5), rgba(0, 31, 62, 0.7)), url('../assets/images/image.jpg'); }"; } ?> Извините за плохое форматирование, но я не могу сделать лучше в комментариях. - person Ameer Taweel; 19.06.2019
comment
Не волнуйтесь, так это не сработает. Заголовок php должен быть определен, как в примере. Поскольку мы пропускаем только некоторые css в скрипте, нет необходимости читать другие файлы, поэтому часть, которую вы можете удалить, это `$file_read = fopen(stylesheet.css,r+); while(! feof($file_read)) { $css= fgets($file_read); эхо $css; }` - person Thorsten Wolske; 19.06.2019

Вы можете использовать элемент HTML picture для определения источников вашего изображения, например:

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg"> 
  <img src="image.jpg">
</picture>

В этом случае, если браузер поддерживает изображения webp, изображение будет служить таковым, в противном случае он прибегнет к классической версии jpg. Очевидно, вам понадобятся обе версии.

Если вам нужно чистое решение css, вам нужно будет использовать обнаружение функций (media) для каждого отдельного браузера, который либо поддерживает, либо не поддерживает webp (в зависимости от метода) и соответствующим образом изменяет изображение. Я бы предложил вариант один.

person Claire    schedule 16.06.2019
comment
На самом деле это работает и действительно полезно, но в моем случае мне нужно реализовать это в CSS, потому что я создаю эффект прокрутки параллакса, и поэтому мне нужен CSS. - person Ameer Taweel; 17.06.2019