การโหลดรูปภาพ 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

1
n1313 ฉันใช้วิธีที่ง่ายที่สุดเท่าที่จะทำได้: $ ('# toggle') คลิก (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ถูกนำมาใช้


27
นี่มันเจ๋งมาก!
Hengjie

4
เทคนิคที่ดีที่สุดสำหรับความเรียบง่ายและแนวทาง CSS ที่บริสุทธิ์! ข้อเสียเปรียบเพียงประการเดียวคือภาพเหล่านี้จะโหลดพร้อมกันกับเนื้อหาที่มองเห็นได้ทันทีและไม่ล่าช้าจนกว่าจะโหลดเนื้อหาหลักซึ่งจะต้องใช้ Javascript แต่ถ้าคุณไม่ได้โหลดภาพไว้ล่วงหน้าหลายสิบภาพสิ่งนี้ไม่ควรเป็นตัวทำลายข้อตกลง
Benjamin

2
นี่เป็นสิ่งที่ยอดเยี่ยมสำหรับการโหลดเนื้อหาที่วางไว้ล่วงหน้าสำหรับปุ่ม CSS และด้วยวิธีนี้คุณจะไม่สั่นไหวเมื่อกดปุ่มของคุณในขณะที่โหลดเนื้อหา
Robert Petz

16
ทางออกที่ดี. ฉันไม่แนะนำให้ใช้สิ่งนี้กับbodyแม้ว่ารูปภาพเหล่านี้จะถูกโหลดลงในทุกหน้าที่อ้างอิงสไตล์ชีท คุณควรใช้.contact_form:after {...}หรือคลาสอื่น ๆ ที่มีระดับโลกน้อยกว่าแทน เว้นแต่ว่าแบบฟอร์มติดต่อของคุณจะอยู่ในทุกหน้า)
CloudMagick

3
@vsync ที่สมเหตุสมผลโดยเฉพาะอย่างยิ่งสำหรับ gif และ reusables ขนาดเล็ก สถานการณ์ที่ฉันเจอเมื่อเร็ว ๆ นี้คือภาพ 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

ขอบคุณที่ง่ายที่สุดของทั้งหมด :)
BetaCoder

4
URL ในคำตอบใช้ไม่ได้อีกต่อไป
Brandon Buck

สวัสดีฉันอัปโหลดเนื้อหาใน URL นั้นอีกครั้ง ( paragraphe.org/slidetoggletest/test.html ) ขออภัยที่พลาดสิ่งนี้ไป ไชโย
Peanuts

25

การโหลดรูปภาพล่วงหน้าโดยใช้แท็ก <link> HTML

ฉันเชื่อว่าผู้เยี่ยมชมส่วนใหญ่ของคำถามนี้กำลังมองหาคำตอบของ"ฉันจะโหลดรูปภาพล่วงหน้าก่อนที่การเรนเดอร์ของเพจจะเริ่มได้อย่างไร" และทางออกที่ดีที่สุดสำหรับปัญหานี้คือการใช้<link>แท็กเนื่องจาก<link>แท็กสามารถบล็อกการแสดงผลเพิ่มเติมของหน้าได้ ดูล่วงหน้า

ตัวเลือกค่าทั้งสองนี้ของแอตทริบิวต์rel( ความสัมพันธ์ระหว่างเอกสารปัจจุบันและเอกสารที่เชื่อมโยง ) เกี่ยวข้องกับปัญหามากที่สุด:

  • prefetch : โหลดทรัพยากรที่กำหนดขณะแสดงผลหน้า
  • พรีโหลด : โหลดทรัพยากรที่กำหนดก่อนเริ่มการเรนเดอร์เพจ

ดังนั้นหากคุณต้องการโหลดทรัพยากร ( ในกรณีนี้คือรูปภาพ ) ก่อนที่จะเริ่มกระบวนการแสดงผลของ<body>แท็กให้ใช้:

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

และหากคุณต้องการโหลดทรัพยากรในขณะที่<body>กำลังแสดงผล แต่คุณวางแผนที่จะใช้ในภายหลังแบบไดนามิกและไม่ต้องการรบกวนเวลาในการโหลดของผู้ใช้ให้ใช้:

<link rel="prefetch" href="RESOURCE_URL">

เป็นที่น่าสังเกตว่าเอ็นจิ้นเบราว์เซอร์ Mozilla จะโหลดเฉพาะprefetchเมื่อเบราว์เซอร์ไม่ได้ใช้งานซึ่งถูกกำหนดโดยnsIWebProgressListenerAPI ดูนี้สำหรับข้อมูลเพิ่มเติม
Matthew Beckman

1
ฉันไม่คิดว่าสิ่งนี้จะบล็อกการแสดงผลจริง: w3c.github.io/preload "ตัวอย่างเช่นแอปพลิเคชันสามารถใช้คีย์เวิร์ดแบบโหลดล่วงหน้าเพื่อเริ่มการดึงทรัพยากร CSS ในช่วงต้นลำดับความสำคัญสูงและไม่ปิดกั้นการแสดงผลซึ่งสามารถ นำไปใช้โดยแอปพลิเคชันในเวลาที่เหมาะสม "
Michael Crenshaw

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 ขอบคุณสิ่งนี้ดูดีทีเดียว แต่ฉันควรใช้รหัสนี้ใน 'head' หรือ inline? ฉันหมายความว่าฉันต้องเติมด้วย html หรือไม่
Peanuts

คุณต้องใช้มันในหัว ฉันคิดว่าคุณสามารถใช้มันใน $ (เอกสาร) พร้อม
mck89

6

สำหรับการโหลดภาพพื้นหลังที่ตั้งไว้ล่วงหน้าด้วย CSS คำตอบที่มีประสิทธิภาพที่สุดที่ฉันคิดขึ้นมาคือโค้ดบางรุ่นที่ได้รับการแก้ไขซึ่งฉันพบว่าใช้งานไม่ได้:

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

ประโยชน์มหาศาลของสิ่งนี้คือคุณไม่จำเป็นต้องอัปเดตเมื่อคุณนำภาพพื้นหลังใหม่ในอนาคตมันจะค้นหาภาพใหม่และโหลดไว้ล่วงหน้า!


ฉันเข้าใจถูกต้องหรือไม่ที่คุณเพิ่มองค์ประกอบที่ซ่อนอยู่สำหรับแต่ละภาพ ไม่ใช่ว่าจะสแกนไฟล์ CSS ของคุณเพื่อหารูปภาพได้ใช่ไหม :)
bvdb

5

หากคุณนำภาพ bg เหล่านี้กลับมาใช้ที่อื่นในไซต์ของคุณเพื่อป้อนแบบฟอร์มคุณอาจต้องการใช้ภาพต่อท้าย ด้วยวิธีนี้คุณสามารถจัดการรูปภาพของคุณจากส่วนกลาง (แทนที่จะมี pic1, pic2, pic3 ฯลฯ ... )

โดยทั่วไปแล้วสไปรต์จะเร็วกว่าสำหรับไคลเอนต์เนื่องจากพวกเขากำลังขอไฟล์เดียว (แม้ว่าจะใหญ่กว่าเล็กน้อย) จากเซิร์ฟเวอร์แทนที่จะเป็นไฟล์หลายไฟล์ ดูบทความ SO เพื่อประโยชน์เพิ่มเติม:

สไปรต์รูปภาพ CSS

จากนั้นอีกครั้งสิ่งนี้อาจไม่เป็นประโยชน์เลยหากคุณใช้เพียงฟอร์มเดียวและคุณต้องการโหลดเฉพาะเมื่อผู้ใช้ร้องขอแบบฟอร์มติดต่อ ...

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


ใช่ CSS Sprites เป็นวิธีที่จะไป ตรวจสอบให้แน่ใจว่าภาพใดภาพหนึ่งในภาพต่อเรียงนั้นปรากฏขึ้นก่อนที่จะเปิดแบบฟอร์มที่ซ่อนอยู่ (เช่นในการโหลดหน้าเว็บ)
สตีฟ

1

วิธีการโหลดภาพพื้นหลังที่ซ่อนอยู่ ด้วยวิธีนี้จะถูกโหลดเมื่อเปิดเพจและจะไม่ใช้เวลาใด ๆ เมื่อสร้างแบบฟอร์มโดยใช้ ajax:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}

1

คุณสามารถใช้ปลั๊กอิน jQuery นี้waitForImageหรือคุณสามารถใส่รูปภาพลงใน div ที่ซ่อนอยู่หรือ (width: 0 และ height: 0) และใช้เหตุการณ์ onload กับรูปภาพ

หากคุณมีเพียง 2-3 ภาพคุณสามารถเชื่อมโยงเหตุการณ์และทริกเกอร์เป็นลูกโซ่ได้ดังนั้นหลังจากทุกภาพคุณสามารถทำโค้ดได้


1

วิธีเดียวคือให้ Base64 เข้ารหัสรูปภาพและวางไว้ในโค้ด HTML เพื่อที่จะไม่ต้องติดต่อเซิร์ฟเวอร์เพื่อดาวน์โหลดรูปภาพ

การดำเนินการนี้จะเข้ารหัสรูปภาพจาก url เพื่อให้คุณสามารถคัดลอกโค้ดไฟล์รูปภาพและแทรกลงในเพจของคุณได้เช่นนั้น ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}

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 แน่นอนว่าคุณยังสามารถใช้บริการอินเทอร์เน็ตที่เร็วขึ้นได้)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.