Предварительная загрузка изображений CSS

118

У меня есть скрытая контактная форма, которая открывается при нажатии на кнопку. Его поля устанавливаются как фоновые изображения CSS, и они всегда появляются немного позже, чем выбранный div.

Я использовал этот фрагмент в <head>разделе, но безуспешно (после очистки кеша):

<script>
$(document).ready(function() {
        pic = new Image();
        pic2 = new Image();
        pic3 = new Image();
        pic.src="<?php bloginfo('template_directory'); ?>/images/inputs/input1.png";
        pic2.src="<?php bloginfo('template_directory'); ?>/images/inputs/input2.png";
        pic3.src="<?php bloginfo('template_directory'); ?>/images/inputs/input3.png";
});
</script>

Я использую jQuery в качестве своей библиотеки, и было бы здорово, если бы я мог использовать его также для решения этой проблемы.

Спасибо за вашу мысль.

Арахис
источник
Пожалуйста, покажите свой код. Как переключить эту форму?
n1313 03
1
n1313, я использую самый простой из возможных способов: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Peanuts

Ответы:

258

Предварительная загрузка изображений только с использованием CSS

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

Чтобы «трюк» сработал, мы будем использовать contentсвойство, которое удобно позволяет установить несколько URL-адресов для загрузки, но, как показано, ::afterпсевдоэлемент скрыт, поэтому изображения не будут отображаться:

body::after{
   position:absolute; width:0; height:0; overflow:hidden; z-index:-1; // hide images
   content:url(img1.png) url(img2.png) url(img3.gif) url(img4.jpg);   // load images
}

Демо


лучше использовать изображение спрайта, чтобы уменьшить количество HTTP-запросов ... (если есть много изображений относительно небольшого размера) и убедитесь, что изображения размещены там, где используется HTTP2 .

VSync
источник
27
Это круто!
Hengjie
4
Лучшая на сегодняшний день техника благодаря своей простоте и чистому подходу CSS! Единственный недостаток в том, что эти изображения загружаются одновременно с видимым содержимым и не задерживаются до тех пор, пока не будет загружено основное содержимое, для чего потребуется Javascript. Но если вы предварительно не загружаете десятки изображений, это не должно помешать сделке.
Бенджамин
2
это фантастика для предварительной загрузки наведенных ресурсов для кнопок CSS и тому подобного - таким образом вы не получите мерцания, когда вы наводите курсор на кнопку во время загрузки ресурсов
Роберт Петц
16
Хорошее решение. Однако я бы рекомендовал не применять это к body, поскольку эти изображения будут загружены на каждую страницу, которая ссылается на таблицу стилей. Вместо этого вы должны использовать .contact_form:after {...}или какой-либо другой менее глобальный класс. Если, конечно, ваша контактная форма есть на каждой странице;)
CloudMagick
3
@vsync, это имеет смысл, особенно для гифок и небольших файлов многократного использования. Ситуация, с которой я столкнулся недавно, была для больших изображений bg для карусели с богатым контентом, и я определенно не хотел, чтобы эти большие файлы загружались повсюду :)
CloudMagick
30

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

Вот тест: http://paragraphe.org/slidetoggletest/test.html

<script>
    var pic = new Image();
    var pic2 = new Image();
    var pic3 = new Image();
    pic.src="images/inputs/input1.png";
    pic2.src="images/inputs/input2.png";
    pic3.src="images/inputs/input3.png";
</script>
Арахис
источник
После нескольких тестов с CSS-ONLY и этим решением, в частности, в моем случае, это лучшее.
zequinha-bsb
Спасибо за
самый
4
URL-адрес в ответе больше не действителен.
Brandon Buck
Привет, я повторно загрузил содержимое по этому URL ( paragraphe.org/slidetoggletest/test.html ), извините за то, что пропустил это. Ура,
Peanuts
25

Предварительная загрузка изображений с использованием тега HTML <link>

Я считаю, что большинство посетителей этого вопроса ищут ответ «Как я могу предварительно загрузить изображение до начала рендеринга страницы?» и лучшим решением этой проблемы является использование <link>тега, потому что <link>тег может блокировать дальнейшее отображение страницы. См. Упреждающий

Эти два варианта значений атрибута rel( отношения между текущим документом и связанным документом ) наиболее актуальны для данной проблемы:

  • prefetch : загрузить указанный ресурс во время рендеринга страницы
  • preload : загрузить указанный ресурс до начала рендеринга страницы

Поэтому, если вы хотите загрузить ресурс ( в данном случае изображение ) до начала процесса рендеринга <body>тега, используйте:

<link rel="preload" as="image" href="IMAGE_URL">

и если вы хотите загрузить ресурс во время <body>рендеринга, но планируете использовать его позже динамически и не хотите беспокоить пользователя временем загрузки, используйте:

<link rel="prefetch" href="RESOURCE_URL">
mertyildiran
источник
Стоит отметить, что движок браузера Mozilla загружается только prefetchтогда, когда браузер находится в режиме ожидания, что определяется nsIWebProgressListenerAPI. См. Это для получения дополнительной информации.
Мэтью Бекман
1
Я не думаю, что это на самом деле блокирует рендеринг: w3c.github.io/preload "Например, приложение может использовать ключевое слово preload, чтобы инициировать раннюю, высокоприоритетную и не блокирующую рендеринг выборку ресурса CSS, которая затем может быть подано приложением в соответствующее время »
Майкл Креншоу
1
@MichaelCrenshaw правильно, <link rel="preload">это не блок рендеринга, я считаю , что автор неправильно определение. Из MDN Preloading content with rel = "preload" , "... который вы хотите начать загружать на ранней стадии жизненного цикла страницы, до того, как сработает основной механизм рендеринга браузеров". Идея состоит в том, что ресурсы извлекаются как можно скорее, что повышает вероятность того, что ресурс будет доступен, когда это необходимо, например, когда <img>элемент отрисовывается.
MDMower
14

http://css-tricks.com/snippets/css/css-only-image-preloading/

Техника # 1

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

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

Техника # 2

Если к рассматриваемому элементу уже применено фоновое изображение, и вам нужно изменить это изображение, вышеуказанное не сработает. Обычно вы выбираете здесь спрайт (комбинированное фоновое изображение) и просто меняете положение фона. Но если это невозможно, попробуйте это. Примените фоновое изображение к другому элементу страницы, который уже используется, но не имеет фонового изображения.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
Фатих Хайриоглу
источник
4
Всегда предоставляйте содержание внешних ссылок. В противном случае ваш ответ ничего не стоит, если ссылка оборвется!
sra
@Fatih +1 за очень хорошую ссылку. Более текущая версия связанной статьи с 3 - мя различными способами здесь perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr
@xmojmr В вашей ссылке нет решений только для CSS.
Макс
10

попробуйте с этим:

var c=new Image("Path to the background image");
c.onload=function(){
   //render the form
}

С помощью этого кода вы предварительно загружаете фоновое изображение и визуализируете форму при ее загрузке.

mck89
источник
mck89, спасибо, выглядит неплохо. Но должен ли я использовать этот код внутри «головы» или в строке? Я имею ввиду, я должен заполнить его html?
Peanuts
Вы должны использовать это в голове. Думаю, вы можете использовать его внутри $ (document) .ready
mck89
6

Для предварительной загрузки фоновых изображений, установленных с помощью CSS, наиболее эффективным ответом, который я придумал, была измененная версия некоторого кода, который, как я обнаружил, не работал:

$(':hidden').each(function() {
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    tempImage = new Image();
    tempImage.src = backgroundImage;
  }
});

Огромным преимуществом этого является то, что вам не нужно обновлять его, когда вы добавляете новые фоновые изображения в будущем, он найдет новые и предварительно загрузит их!

Deminetix
источник
Правильно ли я понимаю, что вы добавляете скрытый элемент для каждого изображения? Это не значит, что он может сканировать ваш файл CSS на предмет изображений, верно? :)
bvdb 01
5

Если вы повторно используете эти изображения bg где-либо еще на своем сайте для ввода формы, вы, вероятно, захотите использовать спрайт изображения. Таким образом, вы можете централизованно управлять своими изображениями (вместо pic1, pic2, pic3 и т. Д.).

Спрайты обычно работают быстрее для клиента, поскольку они запрашивают с сервера только один (хотя и немного большего размера) файл, а не несколько файлов. См. Статью SO для получения дополнительных преимуществ:

CSS-спрайты изображений

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

http://www.alistapart.com/articles/sprites

ajhit406
источник
Да, CSS-спрайты - это то, что вам нужно. Просто убедитесь, что одно из изображений в этом спрайте появляется до запуска скрытой формы (как при загрузке страницы).
Стив
1

как насчет загрузки этого фонового изображения где-нибудь скрыто. Таким образом, он будет загружен при открытии страницы и не будет занимать какое-либо время после создания формы с использованием ajax:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}
Santi
источник
1

Вы можете использовать этот плагин jQuery waitForImage, или вы можете поместить изображения в скрытый div или (ширина: 0 и высота: 0) и использовать событие onload для изображений.

Если у вас есть только 2-3 изображения, вы можете связывать события и запускать их в цепочку, чтобы после каждого изображения вы могли выполнять некоторый код.

user1236048
источник
1

Единственный способ - закодировать изображение в Base64 и поместить его в HTML-код, чтобы ему не приходилось связываться с сервером для загрузки изображения.

Это закодирует изображение с URL-адреса, чтобы вы могли скопировать код файла изображения и вставить его на свою страницу так ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}
Mheager
источник
2
если вы захотите снова использовать то же изображение в своем CSS ... оно не будет кэшировано, и вам придется загрузить его снова.
vsync
1

Когда нет возможности изменить код CSS и предварительно загрузить изображения с помощью правил CSS для :beforeили :afterпсевдоэлементов, можно использовать другой подход с кодом JavaScript, пересекающим правила CSS загруженных таблиц стилей. Для того, чтобы он работал, скрипты должны быть включены после таблиц стилей в HTML, например, перед закрывающим bodyтегом или сразу после таблиц стилей.

getUrls() {
    const urlRegExp = /url\(('|")?([^'"()]+)('|")\)?/;

    let urls = [];
    for (let i = 0; i < document.styleSheets.length; i++) {
        let cssRules = document.styleSheets[i].cssRules;
        for (let j = 0; j < cssRules.length; j++) {
            let cssRule = cssRules[j];
            if (!cssRule.selectorText) {
                continue;
            }

            for (let k = 0; k < cssRule.style.length; k++) {
                let property = cssRule.style[k],
                    urlMatch = cssRule.style[property].match(urlRegExp);
                if (urlMatch !== null) {
                    urls.push(urlMatch[2]);
                }
            }
        }
    }
    return urls;
}

preloadImages() {
    return new Promise(resolve => {
        let urls = getUrls(),
            loadedCount = 0;

        const onImageLoad = () => {
            loadedCount++;
            if (urls.length === loadedCount) {
                resolve();
            }
        };

        for (var i = 0; i < urls.length; i++) {
            let image = new Image();
            image.src = urls[i];
            image.onload = onImageLoad;
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    preloadImages().then(() => {
        // CSS images are loaded here
    });
});
эзз
источник
0

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


источник
мммм ... хорошая точка cpharmston, и это объясняет, почему проблема сохраняется даже с изображениями в кеше. Значит, обходного пути нет?
Peanuts
Создавайте изображения меньшего размера! Файлы JPEG легко сжимаются, есть инструменты командной строки для уменьшения размера PNG ( pmt.sourceforge.net/pngcrush ), и вы можете уменьшить количество цветов в изображении, чтобы уменьшить размер GIF. Конечно, вы также можете