Is this an acceptable way to preload images, compared to some js code inside of html / head
body:after{
display:none;
content:
url(img1.jpg)
url(img2.jpg)
...
}
js way
$.preload = function() {
for (var i = 0; i < arguments.length; i++) {
$("<img />").attr("src", arguments[i]);
}
}
$.preload("img1.jpg","img2.jpg");
The concept behind it is to place the background images on a pseudo-element that is loaded when the page loads but is not shown. This causes the browser to load the images so that when they are called later by another element they are ready to go.
This can be used to preload the images and swap them on hover. The "preload" div has no height/width since the images are set to background, so it doesn't show on the page, and the images are ready when you want to swap them on hover. (you will obviously have to set height/width on the anchors. I'm just showing minimal CSS here to get the point across)
HTML:
<div id="preload"></div>
<div id="icons">
</div>
CSS:
#preload {background: url('pic1b.png'), url('pic2b.png'), url('pic3b.png');}
.button-1 {background: url('pic1a.png');}
.button-2 {background: url('pic2a.png');}
.button-3 {background: url('pic3a.png');}
.button-1:hover {background: url('pic1b.png');}
.button-2:hover {background: url('pic2b.png');}
.button-3:hover {background: url('pic3b.png');}
Obviously, there are many other ways and the post above shared a link that include many others.
http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
I suppose that method would work, as long as the image isn't dynamically generated. The only issue with preloading using just CSS seems to be that the images download WITH the page, not after it. You can trigger the JavaScript event after the pageload is over.
Further reading: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
On firefox, at least, the images don't get cached with display: none. Instead you can set:
body:after {
width: 0; height: 0; overflow: hidden; display: block;
content: url('img1')
url('img2')
...;
}
Related
I tried to change the cursor on my html website with the "cursor" property, but I can only do it embedded, but I want to put it in my css stylesheet. Is that possible?
This is the code that I put between the style tags
* {
cursor: url('plaatjes/cake.cur'), default;
}
changing ur cursor is possbile yeah.
There are different possibilities why ur cursor image is not showing up (image type, image size, image url for
example..)
Try this accepted answer:
so accepted answer
This example changes the cursor for a specific div, if u use this like u have done before (with *) it should work at all.
If you want cursor on whole page, this should work:
first fix width/height of html and body element,
html, body {
height: 100%;
width: 100%;
padding: 0; margin: 0;
}
then:
* {
cursor: url('plaatjes/cake.cur'), default;
}
I'm using the following technique to pre-load images that are applied as CSS background images when hovering buttons:
#preload_area {
background-image:
url(../images/image1.svg),
url(../images/image2.svg);
width: 0px;
height: 0px;
display: inline;
}
Also tried to pre-load just one image, this way:
#preload_area {
background: url(../images/image1.svg) -9999px -9999px no-repeat;
}
None of this works: after hard refresh, when hovering my button the first time, I still see a blink (corresponding to loading the hover image). Obviously after that first time there's no blink any more.
Why is not working on Chrome? (it does work on Firefox)
Why is it not working on Chrome? Because all browser vendors want the fastest browser. They will not load unnessecary assets.
You want a cross browser way to preload? Use a sprite, as [CBroe] suggested. This solution has been around for ages and is rock solid. Any other trick, rendering the image invisible, can work today but be broken tomorrow.
Preloading in CSS doesn't actually mean that the file is loaded before everything else it just means it's the first resource to queue for download from your CSS file.
This means that your HTML has already been retrieved from the server and has probably already queued up or downloaded other resources before the CSS. It's not uncommon for CSS preloaded images to load after all of the HTML content.
Now while the image will be earlier in the queue than other resources referenced in the CSS it doesn't mean that it returns before those other resources. If the size of the file is larger than the other files being queued up it may take longer to be downloaded than those other files which are being downloaded at the same time.
One way to see what is happening with Chrome is to go to your webpage and navigate to the "Network" tab in the Chrome Devtools then refresh the page. It will show you the details of when each item is being loaded and how long that item takes to be received from the server.
Depending what image you're loading and your use case there are several other options.
1) If the file size is large and taking too long to download figure out how to reduce the file size.
2) If you have control of the page the user is navigating from you could prefetch the image for the cache in the prior page.
3) You could also try using HTML preload in addition to the CSS. HTML preloading I believe is only supported by Chrome at the moment so it might be perfect for this scenario. Add the following to the head of your html.
<link rel="preload" as="image" href="image1.svg">
<link rel="preload" as="image" href="image2.svg">
Live Demo:
http://blackmiaool.com/soa/43093224/
No one promise that invisible images will be loaded. Browsers have right to not preload your invisible images, so the css approach in your question may not work in some browsers. The demo above is written by myself. It actually renders image on the screen to guarantee the image is loaded.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>test</title>
</head>
<body>
<h1 style="color:white;text-align:center;">Try to hover</h1>
<div class="show-area"></div>
<link rel="stylesheet" href="style.css">
<script src="../js/jquery.min.js"></script>
<script>
function preloadImage(src, cb) {
//create a image
const $dom = $("<img />", {
src: src
});
//check whether the image is already loaded
if ($dom[0].naturalWidth) {
cb && cb();
return;
}
//Put the image at the left bottom of the screen, and set its opacity to 0.01 to keep it from people eyes.
//Since it's actually rendered on the screen, the browser must load the image
$dom.css({
opacity: 0.01,
position: 'fixed',
bottom: 0,
left: 0,
height: 1,
width: 1,
'z-index': 10000,
'pointer-events': 'none',
});
$(document.body).append($dom);
//listen its `load` event to remove it and invoke callback
$dom.on("load", function() {
$dom.remove();
cb && cb();
});
}
//try to get the urls in the css file, and preload them
$("link").each(function() {
const href = $(this).attr("href");
$.get(href, function(style) {
const urls = [];
let match = style.match(/url\([\s\S]+?\)/g);
match.forEach(function(str) {
str = str.replace(/\s/g, "")
.replace(/^url\(/, "")
.replace(/\)$/, "");
let url = str.match(/^["']?([\S]+?)["']?$/);
if (!url || !url[1]) {
console.warn("Can't find url of " + str);
} else {
url = url[1];
preloadImage(url);
}
});
});
});
</script>
</body>
</html>
css:
body{
margin: 0;
background-color: black;
}
.show-area {
height: 100px;
width: 300px;
margin: auto;
margin-top: 100px;
background: url( ./1.jpg) no-repeat center;
background-size: contain;
}
.show-area:hover {
background-image: url("./2.jpg ");
}
Made a test with chrome, it seams that the image is loaded. The blink is due to place the image i think. To beter understand take a look at this test.
A test with a very big image
div#preload_area::before {
content: " ";
background: url(http://gfsnt.no/oen/foto/Haegefjell_Jan_2013_Large.jpg) no-repeat;
}
div#preload_area {
width: 50%;
height:100vh;
}
div#preload_area:hover {
background: url(http://gfsnt.no/oen/foto/Haegefjell_Jan_2013_Large.jpg);
background-repeat:no-repeat;
background-size:100% auto;
}
IMHO, this is no preloading. It's just loading, and you use a trick to display the right image when you hover the button.
If you really want to preload, or, as I understand your need, "you want the image already there, when you try to hover the button", then you have different options:
prefetch:
<link rel="prefetch" href="image1.svg">
<link rel="prefetch" href="image2.svg">
A nice thing to add for this is that "there's no same-origin restriction for link prefetching".
preload:
<link rel="preload" href="image1.svg">
<link rel="preload" href="image2.svg">
With "preload", the resources must be downloaded, whereas it's not always the case with prefetch.
Preload is supported by Chrome, Opera, Android browser and some more, but no Firefox & others. More details here
These techniques are described in more depth on css-tricks.com
Hope this helps you.
If you donĀ“t want loading-gaps, you could use a sprite-image, or you can set the background image as base64 encoded image. In this case, the images are always loaded when the css file is loaded.
.myImg {
background-image: url(data:image/svg+xml;base64,PD9...);
}
Here you can convert your svg images to base64: http://b64.io
I recently use this for "back to top" button in my blog http://anggit.com.
Will it works for you?
CSS:
<style>
#to_top {
display: block;
width: 48px;
height: 48px;
overflow: hidden;
}
#to_top img { /* in case the actual image size is over 48px */
width: 48px;
height: 48px;
}
#to_top:hover #image-1 { /* hover will remove the 1st image, the 2nd image will appear */
display: none;
}
</style>
HTML:
<a id="to_top" href="#">
<img id="image-1" src="image48x48.png" alt="Top" />
<img id="image-2" src="image48x48-hover.png" alt="Top" />
</a>
I'm programming gallery of images, with specific hover effect. When user comes over the image, I use ::before pseudoelement to create "curtain" over the div with image using mix-blend-mode CSS property:
div.img::after {
content: "";
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 2;
mix-blend-mode: soft-light;
background-color: red;
}
Resulting effect is like this:
But unluckily, IE (and some others according to caniuse) does not support this property and displays full red rectangle over the image and therefore it is not visible.
Is it possible to hack this mix-blend-mode behaviour to act like in Firefox or Chrome?
If not, is it possible to hide covering div or set it semi-transparent if and only-if mix-blend-mode is not supported?
Thank you
I know this is an old question, but you can also use the #supports feature query to detect if a certain property is or isn't available.
#supports not (mix-blend-mode: multiply) {
.image {
...
}
}
If you're interested, you can read more about the feature query at: https://developer.mozilla.org/en-US/docs/Web/CSS/#supports
If you don't want to use plain opacity as a fallback:
Approaches to cross-browser support
Javascript polyfill
This will be slow, and will not allow you to easily animate. However, it will let you create an alternate image for each of your matching images, and you can then fade the opacity or do other CSS transition tricks between the two.
http://codepen.io/brav0/pen/bJDxt (not my pen - uses multiply, not soft light)
Server side processing
Wouldn't be my first choice, but if you control the server-side code, you can prepare alternate images using server side imaging libraries (GD, etc)
Only enabling the effect for supporting browsers
Css hacks for detecting IE
#media screen { #media (min-width: 0px) {
div.img::after{ ... }
} }
Using JavaScript
if (window.getComputedStyle(document.body).mixBlendMode !== undefined)
$("div.img").addClass("curtain");
...and the CSS...
img.curtain::after { ... }
I am currently hitting an issue in IE 10 and 11 where the browser tab is hanging every now and then on Layout in the UI Responsiveness tool. I am part of a team writing a fairly large knockout.js web app, so nailing down the exact condition that is creating this issue has been extremely difficult. From what I can tell, the browser tab hangs when Layout is performed when the removal of loading indicator HTML is removed from the page and some divs plus an empty SVG tag is appended to the DOM in its place.
I have been able to nail down that the empty SVG tag is the culprit, but I do not know why and I cannot remove that tag from the page is it is an important element to a D# data visualization that I am trying to create.
Here is the US Responsiveness report that IE 11 has provided me. I have zoomed in on the problematic area, and as you can see in the picture, the Layout thread spikes the CPU to 100%.
Before I get into the code samples my question is:
Why would the browser tab intermittently freeze/hang from adding an empty SVG element to the page?
The HTML gets appended to the DOM via javascript in as minimal of a way as possible from my research on reducing reflow in the browser:
var contentHTML = "";
contentHTML += '<div class="axis-title y-axis-title">' + renderString(bindingData.yAxis.title) + "</div>";
contentHTML += '<div class="' + CANVAS_CLASS + '"></div>';
contentHTML += '<svg class="x-axis"></svg>'; // The problematic element
element.innerHTML = contentHTML;
This results in the following HTML (note: all of the data-bind stuff is for knockout.js binding handlers, which triggers the JS above):
<div class="chart" data-bind="
barChart: {
data: rowData,
categoryTextKey: 'label',
valueKey: 'keyOnObject',
xAxis: {
title: 'xAxisTitle',
domain: [-1, 1]
},
yAxis: {
title: 'yAxisTitle'
},
onClick: onLabelClick,
formatValueText: formatPercentage
}
"></div>
<div class="axis-title y-axis-title">Y Title</div>
<div class="chart-canvas"></div>
<svg xmlns="http://www.w3.org/2000/svg" class="x-axis" />
<div class="axis-title x-axis-title">X Title</div>
</div>
Lastly, I also am using flexbox CSS rules to lay out my HTML. I am not sure if that is affecting this issue, but here is the CSS in case it helps:
.chart {
.flexbox();
.flex-direction(column);
height: 100%;
width: 100%;
.chart-label-click {
cursor: pointer;
}
.chart-header,
.axis-title,
.x-axis {
.flex-grow(0);
.flex-shrink(0);
}
.chart-canvas {
.flex-grow(1);
.flex-shrink(1);
overflow-x: hidden;
overflow-y: auto;
width: 100%;
}
.chart-canvas svg {
display: block;
width: 100%;
}
.axis-title {
font-weight: bold;
}
.x-axis {
.flexbox();
.flex-grow(0);
.flex-basis(20px);
margin-bottom: 5px;
overflow: visible;
width: 100%;
}
.x-axis line,
.x-axis path {
fill: none;
stroke: #d1d1d1;
stroke-width: 1px;
shape-rendering: crispEdges;
}
}
Thank you for any help you may have. I am not sure how to nail this down is it is intermittent in one section of our app and our codebase is pretty big to figure out the exact combination of code in other files that may also be contributing to this issue.
The described issue seems to be this bug:
https://connect.microsoft.com/IE/feedback/details/796745/mouse-events-are-not-delivered-at-all-anymore-when-inside-an-svg-a-use-is-removed-from-the-dom
In the comments is a workaround described which at least worked for us:
You have to set style="pointer-events: none;" on the use elements.
Or simply add this to your css:
svg use { pointer-events:none; }
But be aware that this also disables any mouse events triggered on the use element.
The way I ultimately fixed this issue was to remove the use of display:flex on the .chart element. In its place, I used a fixed height and display:block. It looks like this is ultimately a bug w/ IE when mixing SVG and flexbox together.
Make sure your code isn't setting a value in JavaScript (or other language) without even the quotes such as the following...
var a = ;//[var][space][a][space][=][space][;]
That will freeze up IE11 (not sure about 10 offhand).
After many days of searching I decided to solve the problem in addressing this:
svg use { pointer-events:none; }
I have 30 buttons of different sizes and I want to set the width of all at once through CSS. But I haven't been able to get it to work right.
[insert example of failed CSS code here]
But it doesn't work. For example, the following button doesn't follow the above rule:
[insert minimal, complete HTML example here that illustrates the issue]
If you need to do this explicitly, you can simply add the !important attribute, although this will guarantee that regardless of location or source, the width property will be overridden, so be sure that you definitely want to apply that style.
button {
width: XXXpx !important;
}
EDIT
To make the above style only apply to one HTML page, as per your request, you can change the HTML for that page slightly, giving an id to your <body> tag, and then targeting buttons only when they appear below that id.
HTML
<body id="page_title">
CSS
#page_title button {
width: XXXpx !important;
}
You can create a button class in your css
.button
{
width: ____px;
}
and then in your .aspx add cssClass="button" to your ASP buttons (I assume they're asp.net controls?)
For input element
INPUT[type="submit"] {
width: XXXpx;
}
For button
BUTTON {
width: XXXpx;
}
Assuming your buttons have something unique in common (ie. they're all have the class name of "buttons"), you can just use a CSS selector to set their width property. ie.
.buttons {
width:100px;
}
There are a number of different selectors you can use to target them, and keep in mind you can have multiple classnames on each html element by putting a space between them. ie. <div class='nav button'></div> will respond to both the .nav and .button definitions.