Wstępne ładowanie obrazów CSS

118

Mam ukryty formularz kontaktowy, który jest uruchamiany po kliknięciu przycisku. Jego pola są ustawione jako obrazy tła CSS i zawsze pojawiają się nieco później niż zmieniony element div.

Używałem tego fragmentu w <head>sekcji, ale bez powodzenia (po wyczyszczeniu pamięci podręcznej):

<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>

Używam jQuery jako mojej biblioteki i byłoby fajnie, gdybym mógł go również użyć do uporządkowania tego wydania.

Dzięki za przemyślenia.

Orzeszki ziemne
źródło
Proszę, pokaż swój kod. Jak przełączać ten formularz?
n1313
1
n1313, używam najprostszego możliwego sposobu: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Fistaszki

Odpowiedzi:

257

Wstępne ładowanie obrazów tylko przy użyciu CSS

W poniższym kodzie losowo wybieram bodyelement, ponieważ jest to jeden z jedynych elementów, które mogą istnieć na stronie.

Aby „sztuczka” zadziałała, użyjemy contentwłaściwości, która pozwala wygodnie ustawić wiele adresów URL do załadowania, ale jak pokazano, ::afterpseudoelement jest ukryty, więc obrazy nie będą renderowane:

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
}

Próbny


lepiej jest użyć obrazu sprite, aby zmniejszyć liczbę żądań http ... (jeśli jest wiele obrazów o stosunkowo małych rozmiarach) i upewnić się, że obrazy są hostowane tam, gdzie używany jest protokół HTTP2 .

vsync
źródło
27
To jest niesamowite!
Hengjie,
4
Jak dotąd najlepsza technika ze względu na prostotę i czyste podejście CSS! Jedyną wadą jest to, że te obrazy są ładowane w tym samym czasie, co natychmiast widoczna treść i nie są opóźniane do momentu wczytania głównej treści, co wymagałoby Javascript. Ale jeśli nie ładujesz wstępnie dziesiątek obrazów, nie powinno to zrywać umowy.
Benjamin
2
jest to fantastyczne do wstępnego ładowania zasobów najechania na przyciski CSS i tym podobnych - w ten sposób nie pojawia się migotanie, gdy przechodzisz nad przyciskiem podczas ładowania zasobów
Robert Petz
16
Dobre rozwiązanie. Nie radziłbym jednak stosować tego do bodytego, ponieważ te obrazy zostaną załadowane na każdą stronę, która odwołuje się do arkusza stylów. Zamiast tego powinieneś użyć .contact_form:after {...}lub innej klasy, która jest mniej globalna. Chyba że, oczywiście, twój formularz kontaktowy znajduje się na każdej stronie;)
CloudMagick
3
@vsync, to ma sens, szczególnie w przypadku gifów i małych elementów wielokrotnego użytku. Sytuacja, z którą ostatnio się spotkałem, dotyczyła dużych obrazów bg dla karuzeli bogatej w zawartość i na pewno nie chciałem, aby te duże pliki były ładowane wszędzie :)
CloudMagick
30

Mogę potwierdzić, że mój oryginalny kod wydaje się działać. Od niechcenia trzymałem się obrazu z niewłaściwą ścieżką.

Oto test: 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>
Orzeszki ziemne
źródło
Po kilku testach z TYLKO CSS i tym rozwiązaniem, w moim przypadku, jest to najlepsze rozwiązanie.
zequinha-bsb
Dzięki, to najłatwiejsze ze wszystkich :)
BetaCoder
4
Adres URL w odpowiedzi jest już nieaktualny.
Brandon Buck
Cześć, ponownie załadowałem zawartość pod tym adresem URL ( paragraphe.org/slidetoggletest/test.html ), przepraszam, że to przegapiłem. Pozdrawiam,
Fistaszki
25

Wstępne ładowanie obrazów za pomocą tagu HTML <link>

Wydaje mi się, że większość odwiedzających to pytanie szuka odpowiedzi „Jak mogę wstępnie załadować obraz przed rozpoczęciem renderowania strony?” a najlepszym rozwiązaniem tego problemu jest użycie <link>tagu, ponieważ <link>tag może blokować dalsze renderowanie strony. Zobacz zapobiegawcze

Te dwie opcje wartości atrybutu rel( związek między bieżącym dokumentem a połączonym dokumentem ) są najbardziej istotne w przypadku problemu:

  • pobieranie wstępne : załaduj podany zasób podczas renderowania strony
  • preload : załaduj podany zasób przed rozpoczęciem renderowania strony

Jeśli więc chcesz załadować zasób ( w tym przypadku obraz ) przed rozpoczęciem renderowania <body>tagu, użyj:

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

a jeśli chcesz załadować zasób podczas <body>renderowania, ale planujesz użyć go później dynamicznie i nie chcesz zawracać użytkownikowi głowy czasem ładowania, użyj:

<link rel="prefetch" href="RESOURCE_URL">
mertyildiran
źródło
Warto zauważyć, że silnik przeglądarki Mozilla ładuje się tylko prefetchwtedy, gdy przeglądarka jest bezczynna, co jest określane przez nsIWebProgressListenerAPI. Zobacz to aby uzyskać więcej informacji.
Matthew Beckman
1
Nie sądzę, żeby to faktycznie blokowało renderowanie: w3c.github.io/preload "Na przykład aplikacja może użyć słowa kluczowego preload, aby zainicjować wczesne pobieranie zasobu CSS bez blokowania renderowania i o wysokim priorytecie. być stosowane przez aplikację w odpowiednim czasie "
Michael Crenshaw
1
@MichaelCrenshaw jest poprawny, <link rel="preload">czy nie blokuje renderowania, uważam, że autor źle definicji. Z MDN Preloading content with rel = "preload" , "... który chcesz rozpocząć ładowanie na wczesnym etapie cyklu życia strony, zanim włączy się główna maszyna renderująca przeglądarki." Chodzi o to, że zasoby są pobierane tak szybko, jak to możliwe, co zwiększa prawdopodobieństwo, że zasób będzie dostępny w razie potrzeby, na przykład podczas <img>renderowania elementu.
MDMower
14

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

Technika nr 1

Załaduj obraz na zwykły stan elementu, przesuń go tylko z pozycją w tle. Następnie przesuń położenie tła, aby wyświetlić je po najechaniu kursorem.

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

Technika nr 2

Jeśli dany element ma już zastosowany obraz tła i musisz go zmienić, powyższe nie zadziała. Zazwyczaj wybrałbyś tutaj sprite'a (połączony obraz tła) i po prostu przesunąłbyś pozycję tła. Ale jeśli to nie jest możliwe, spróbuj tego. Zastosuj obraz tła do innego elementu strony, który jest już używany, ale nie ma obrazu tła.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
Fatih Hayrioğlu
źródło
4
Zawsze podawaj zawartość linków zewnętrznych. W przeciwnym razie twoja odpowiedź będzie bezwartościowa, jeśli łącze się zepsuje!
sra
@Fatih +1 za bardzo dobry link. Bardziej aktualna wersja połączonego artykułu z 3 różnymi sposobami jest tutaj perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr
@xmojmr W Twoim linku nie ma rozwiązań obejmujących tylko CSS.
Max
10

spróbuj z tym:

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

Za pomocą tego kodu wstępnie ładujesz obraz tła i renderujesz formularz po załadowaniu

mck89
źródło
mck89, dzięki, wygląda całkiem nieźle. Ale czy powinienem używać tego kodu w nagłówku czy w tekście? Mam na myśli, czy muszę go wypełnić html?
Peanuts
Musisz użyć go w głowie. Myślę, że możesz go użyć wewnątrz $ (document) .ready
mck89
6

Jeśli chodzi o wstępne ładowanie obrazów tła ustawionych za pomocą CSS, najbardziej wydajną odpowiedzią, jaką wymyśliłem, była zmodyfikowana wersja kodu, który nie działał:

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

Ogromną zaletą tego jest to, że nie musisz go aktualizować, gdy w przyszłości wprowadzisz nowe obrazy tła, znajdzie nowe i wstępnie je załaduje!

Deminetix
źródło
Czy dobrze rozumiem, że dodajesz ukryty element do każdego obrazu? Nie chodzi o to, że jest w stanie przeskanować plik CSS w poszukiwaniu obrazów, prawda? :)
bvdb
5

Jeśli ponownie używasz tych obrazów bg gdziekolwiek indziej w witrynie do wprowadzania formularzy, prawdopodobnie chcesz użyć sprite'a obrazu. W ten sposób możesz centralnie zarządzać swoimi obrazami (zamiast mieć pic1, pic2, pic3 itd ...).

Sprity są generalnie szybsze dla klienta, ponieważ żądają tylko jednego (choć nieco większego) pliku z serwera zamiast wielu plików. Zobacz artykuł SO, aby uzyskać więcej korzyści:

Obrazek CSS

Z drugiej strony może to wcale nie być pomocne, jeśli używasz ich tylko w jednym formularzu i naprawdę chcesz je załadować tylko wtedy, gdy użytkownik zażąda formularza kontaktowego ... może jednak mieć sens.

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

ajhit406
źródło
Tak, CSS Sprite to droga do zrobienia. Po prostu upewnij się, że jeden z obrazów w tym duszku pojawia się przed uruchomieniem ukrytego formularza (jak podczas ładowania strony).
Steve
1

co powiesz na załadowanie tego obrazu tła gdzieś ukrytego. W ten sposób zostanie załadowany po otwarciu strony i nie zajmie czasu po utworzeniu formularza przy użyciu ajax:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}
Santi
źródło
1

Możesz użyć tej wtyczki jQuery waitForImage lub możesz umieścić obrazy w ukrytym div lub (szerokość: 0 i wysokość: 0) i użyć zdarzenia onload na obrazach.

Jeśli masz tylko 2-3 obrazy, możesz wiązać zdarzenia i uruchamiać je w łańcuchu, więc po każdym obrazie możesz wykonać kod.

user1236048
źródło
1

Jedynym sposobem jest zakodowanie obrazu w Base64 i umieszczenie go w kodzie HTML, aby nie musiał kontaktować się z serwerem w celu pobrania obrazu.

Spowoduje to zakodowanie obrazu z adresu URL, dzięki czemu możesz skopiować kod pliku obrazu i wstawić go na swoją stronę w ten sposób ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}
mheager
źródło
2
jeśli zechcesz ponownie użyć tego samego obrazu w swoim CSS ... nie zostanie on zapisany w pamięci podręcznej i będziesz musiał go ponownie załadować.
vsync,
1

Gdy nie ma możliwości zmodyfikowania kodu CSS i wstępnego załadowania obrazów z regułami CSS :beforelub :afterpseudoelementami, można zastosować inne podejście z przechodzeniem kodu JavaScript w regułach CSS załadowanych arkuszy stylów. Aby to działało, skrypty powinny być dołączane po arkuszach stylów w HTML, na przykład przed bodytagiem zamykającym lub zaraz po arkuszach stylów.

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
    });
});
ezze
źródło
0

Jeśli elementy strony i ich obrazy tła są już w DOM (tj. Nie tworzysz / nie zmieniasz ich dynamicznie), to ich obrazy tła zostaną już załadowane. W tym momencie możesz przyjrzeć się metodom kompresji :)


źródło
mmmm ... dobra uwaga cpharmston, a to wyjaśnia, dlaczego problem występuje nawet w przypadku obrazów w pamięci podręcznej. Czy to oznacza, że ​​nie ma obejścia?
Fistaszki
Twórz mniejsze obrazy! Pliki JPEG są łatwo kompresowane, istnieją narzędzia wiersza poleceń do zmniejszania rozmiaru PNG ( pmt.sourceforge.net/pngcrush ), a także można zmniejszyć liczbę kolorów obrazu, aby zmniejszyć rozmiar GIF. Oczywiście można też