I have an image, say 320 x 240 pixels in size, which I want to display doubled in size (i.e. 640 x 480 pixels) on a web page. In the past, I have done this by setting width=640 on the img tag.
However, I have just spotted the following in the HTML specification:
The dimension attributes are not intended to be used to stretch the image.
In that case, how do I double the size of an image on a web page without going against what the spec intends?
You can use CSS instead. The two methods that jump to mind are using the width or scale transformation.
E.g. img { width: 640px; }. This will keep the proper aspect ratio without specifying the height.
img {
width: 640px;
}
<img src="http://www.placehold.it/320x240">
E.g. img { transform: scale(2) }
img {
transform-origin: top left;
transform: scale(2);
}
<img src="http://www.placehold.it/320x240">
You can set the dimension of the parent image container
.imageContainer {
width: 640px;
height: 480px;
}
img {
width: 100%;
height: 100%
}
<div class="imageContainer">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqdnZQDnZOOyBGXXB23WS87IAxZ85drC-ylgrqWCqYk2aEh3Vo">
</div>
Via CSS, ideally in a style sheet, but in the style attribute if necessary.
For instance, here's your 32x32 gravatar stretched to 128x128:
.stretch-128 {
width: 128px;
height: 128px;
}
<img src="https://www.gravatar.com/avatar/6b938dc4205cd0cea4e4e68451c42a21?s=32&d=identicon&r=PG" class="stretch-128">
Naturally, any time you stretch an image like that, the quality is likely to suffer.
First I created a div with a class named divWrapper with a specific size. We then create a class for our image with a width of 100%(which spans across the divWapper), and added a height of auto(To automatically keep the height in proper proportion). You can adjust the size of the image according to the divWapper class.
.divWrapper{
width:640px;
height:480px;
float:left;
}
//Now set you image class to
.imageclass{
width:100%
height:auto;
float:left;
}
<div class="divWrapper">
<image class="imageclass" src="https://upload.wikimedia.org/wikipedia/commons/2/2d/Picea_glauca_taiga.jpg">
<div>
This will keep the image in proportion no matter what size the wrapper container is.
A Helpful Note:
You must have a high quality image from the start I suggest using vector images. I prefer to Use PNG or SVG. It has better quality than jpeg and others.
Here are a couple of link that describes a little about image extensions.
https://blog.online-convert.com/best-image-file-extensions/
https://www.sitepoint.com/gif-png-jpg-which-one-to-use/
There are at least 4 ways to do this.
1. directly set width attribute of img
principle: modify the width of the image.
set width: 640px; display: block for the img tag.
2. wrap img with a div
principle: inherit the width from parent node.
div width: 640px
img display: block; width: 100%
3. set the image as background of a div
principle: the image is no longer a img tag, but the background of a node.
div background-image: url(), use the image as background image.
div background-size: {2x width} {2x height}, to resize the size of the image
4. scale the image into 2x
set the transform property to scale(2), which means I want the size of it 2 times of its original size
tips: also, we need to set the property transform-origin into top left, in order that it can start from the position(relatively) top: 0; left: 0;
Run the snippet and have a look :)
.method-1 {
display: block;
width: 640px;
}
.method-2 {
width: 640px;
}
.method-2 img {
display: block;
width: 100%;
}
.method-3 {
width: 640px;
height: 480px;
background-image: url(http://www.placehold.it/320x240);
background-size: 640px 480px;
}
.method-4 {
transform-origin: top left;
transform: scale(2);
}
<h1>method 1: img displays as block, width 640px</h1>
<img src="http://www.placehold.it/320x240" class="method-1" />
<br/>
<h1>method 2: parent dom width 640px, img width 100%.</h1>
<div class="method-2">
<img src="http://www.placehold.it/320x240" />
</div>
<br/>
<h1>method 3: the img as div's background, use the background-size attribute to set 2x size.</h1>
<div class="method-3"></div>
<br/>
<h1>method 4: use CSS3 transform property to scale the image into 2x.</h1>
<p>tips: when we set `transform: scale(2);`, we also need to define the `transform-origin` property to `top left`, in order that the image will align from top to bottom as well as from left to right, or it will lost itself. LOL.</p>
<img src="http://www.placehold.it/320x240" class="method-4" />
Here's a list of things you want to avoid when loading an image:
FOUC - which happens when the browser does not have the image size before loading it (in which case it doesn't allocate any space for it until it's fully loaded) or telling the browser the wrong size
distortion (displaying an image at a different aspect ratio than 1:1)
pixelation (displaying an image at a significantly bigger size than its native size)
loading images with significantly bigger native size than the size in page - they slow the page down and consuming unnecessary bandwidth
There are ways to deal with each of the above.
For avoiding FOUC, there are a few methods:
have the image sizes (or ratio) saved, besides the file itself, so you can allocate the correct space in page flow, before loading the images (WP does this out of the box, for example and most themes use it to avoid FOUC)
have the image load in a container, as background image with background-size: cover, so FOUC is not possible, as the document already knows the size of the element, before the image is loaded. This technique also has the advantage of not displaying broken image anchors when an image fails to load. Also, this technique is widely used today in full screen image layouts, some of them using parallax effect. Has the disadvantage of cropping top/bottom or left/right, depending on aspect ratio difference between container and image.
load the image in a position:absolute centered container and when you have its size (and are able to calculate exact position in document flow) animate its scale from 0 to 1 while also animating its container size from "default" to proper size.
Regarding distortion, there isn't much to say, except do not do it. Any other option is better than distortion: cropping, pixelation, even FOUC. Distortion basically says: "Don't trust me with design tasks - I'm unable to tell does from donts" - which, to many, translates to: "I'm unqualified for professional frontend development. I'll mess up any website coming my way, most likely without knowing".
On pixelation. It's a tricky one: you want the page to load as fast as possible, but also want crisp images. When dealing with very large background images, a neat trick is to add a pattern over the image (stripes, dots or any other such semi-transparent patterns - an artistic touch to make pixellation a lot less noticeable).
Another good and smart technique for getting best of both worlds (speed and image quality) is to:
load a proportional thumbnail versions for every image below the fold (yes, they'll look pixelated) and display them at .65 opacity. Lazy load the full size images before they are scrolled into view. Even if the pixelated version is visible for a short while, it will be replaced by the full-size one, creating a focus-in effect, together with changing opacity to 1. If you have quality, outstanding images, you really want this effect (a) because it makes them stand out and b) because you want to load the images at proper, crisp size). The images will look "alive" and get subtle focus, leaving visitors with the impression of looking at a highly sophisticated website.
Avoid oversizing. Here src-set comes into play, combined with the thumbnail loaders described above. And, of course: lazy-loading. Always lazy load anything below the fold. It makes a big difference.
In short, that's how you correctly load images. In reality, it's a huge subject, I haven't even touched optimization, raster vs vectors, svg's or webp formats.
You can achieve this by two way as below.
<img class="xx" src="http://placehold.jp/150x150.png">
.xx {
zoom: 200%;
}
.xx {
transform: scale(2);
}
Generally I haven't found an article providing a way to scale images with client side technologies (leave it the browser's mechanism) without losing some quality.
With that being said I am afraid that If you want the best way to double your image according to HTML Standard specifications the best answer is to use a different image. A scaled up image through back-end process or through Photoshop. Now if you want adaptive image according to the user's screen since most probably this is the actual case the HTML Standard to achieve that is with the following way:
<picture>
<source srcset="http://www.placehold.it/320x240" media="(min-width: 600px)">
<source srcset="http://www.placehold.it/640x480" media="(min-width: 900px)">
<img src="http://www.placehold.it/160x120">
</picture>
Out of my experience the best way to double the size of any image for usage in websites is to actually double the image in a program like Photoshop and then upload it.
The image size, the pixel density for the retina screens, and the plethora of different screen sizes makes working with images a little more advanced than it used to be, but nothing too hard.
check the following example:
<picture>
<source
sizes="(width < 32em) contain, (width >=32em) contain 80vw calc(100vh - 10em)"
srcset="full.jpg 2048h 1024w, half.jpg 1024h, quarter.jpg 512h, eighth.jpg 256h" />
<img src="eighth.jpg" alt="rose flower!" />
</picture>
You upload a relatively big image, at least FHD, or bigger, and then with the 'sizes' and 'srcset' you configure it, which one to load depending on the screen size/type.
This way you cover any potential resolution, small or big, and you always display the best version of your image.
Ok, i admit it, there is some manual labor work to happen in every image prior the uploading, but the final result is worth it!
Now if you insist of keeping the same small image file and double it via using coding, then the best way is to add a CSS class to your image, and on that class specify your doubled dimensions, and that's it.
Here is a funny and good explanation about images srcset, sizes, and the importance of why we need to do it this way.
A fun article on srcset
You can user javascript for like this way this to change image size by it's double
Check this JsFiddle Demo
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
var img = $("#sky");
// Create dummy image to get real size
$("<img>").attr("src", $(img).attr("src")).load(function(){
var realWidth = this.width;
var realHeight = this.height;
alert("Original width=" + realWidth + ", " + "Original height=" + realHeight);
var newWidth = realWidth * 2;
var newHeight = realHeight * 2;
$("#sky").width(newWidth);
$("#sky").width(newHeight);
alert("new Image Size" + newWidth+"x"+newHeight);
});
});
});
</script>
</head>
<body>
<img src="https://www.cluedin.net/images/providers/stackoverflow.png" id="sky" width="250" alt="Cloudy Sky" contextmenu="skymenu">
<p><button type="button">Get Original Image Size And Double it</button></p>
</body>
</html>
I like most of the previous solutions, but the issue here is that we don't actually know the current image size to double it!!
So, my solution is kinda dynamic, and it won't affect other images on your website as well.
Also, it can be enhanced to triple their sizes, and more if you wanted!
Check a Live Preview here.
Or read it below:
HTML
<img class="resize-double" src="https://placeimg.com/100/50/nature">
<img src="https://placeimg.com/200/100/nature">
JavaScript
// Select all images to be resized
const toResizeImgs = document.querySelectorAll(".resize-double");
// Loop over those images and double their size
for(let i=0; i < toResizeImgs.length; i++) {
toResizeImgs[i].style.width = toResizeImgs[i].offsetWidth * 2 + "px";
toResizeImgs[i].style.height = toResizeImgs[i].offsetHeight + "px";
}
It would select the images with the class resize-double, loop on them and change their width/height to 2x of the current one!
NOTE: BothoffsetWidth and offsetHeight return the current width/height including Margins, Paddings and Borders. If it doesn't suit you, you can use clientWidth and clientHeight, or even scrollWidth and scrollHeight based on your needs!
The most optimal way is to load the biggest image to your site and downscale it where you need through CSS.
1) Best quality for your image since upscaling distorts the image.
2) No need to load more images with different sizes
3) Downscaling does not spoil the image and it is just some lines of CSS
If you don't want to load the bigger image, the second best and fastest solution is to upscale it through CSS. Width attribute no longer works in <img>
You can do that many various ways. But whatever you do, first download your image which size you want it to mean the double size otherwise if you double the size, then it gets pixelated or looks faded.
image{ transform: scale(2); }
Try transform scale to double sized your image
Try setting the width in the image with CSS
Try with JavaScript with setAttribute("width", "size")
Well you can use css and avoid stretching.
img{ width:640px; background-size: cover; height:auto;}
This will stretch your image equally with suitable height. You can also try setting height to a specific number.
The dimension attributes are not intended to be used to stretch the image.
As you already mentioned that using width attribute doesn't intend to stretch the image. so in that case we should use transform: scale(2); which is a good idea but this may also get conflict regarding image overlapping other content, so best idea is to use 2x width of div with image scaled 2x with css property 'transform: scale(2);'
Hence: using the below style should be a good idea.
.img2x_container {
width: 640px;
height: 480px;
}
.img2x_container img {
transform: scale(2);
}
This use case is only beneficial when we know the image height and width.
You can make use of transform -> scale
img#imagId {
-ms-transform: scale(2); /* IE 9 */
-webkit-transform: scale(2); /* Safari 3-8 */
transform: scale(2);
}
I use following Java Script code to scale image according which can fit best in container. You may make few changes per your need.
function scaleImage(container, image) {
var c = document.getElementById(container);
var i = document.getElementById(image);
var newSize = scaleSize(c.clientWidth, c.clientHeight, i.width, i.height);
i.style.width = newSize.width;
i.style.height = newSize.height;
c.style.backgroundColor = "transparent";
c.style.border = "none";
var intHeight = ((100-((parseFloat(i.style.height)/87)*100))/2);
var strHeightPercentage = intHeight.toString().concat("%");
c.style.top = strHeightPercentage;}
function scaleSize(maxW, maxH, currW, currH) {
var ratio = currH / currW;
if (currW >= maxW && ratio <= 1) {
currW = maxW;
currH = currW * ratio;
}
else if (currH >= maxH) {
currH = maxH;
currW = currH / ratio;
}
return { width: currW, height: currH };
}
CSS trick, setting just one property
If you want to use CSS, there's a really good way:
img#image_id {
width: calc(2 * 320px);
height: auto; /* This can be omitted */
}
This is very useful which you can change the scale of the image by changing just one number (i.e. the factor). No worries about the image height, it will be set automatically by the browser, even if you omit setting image height to auto (because auto is the default value of width and height; see this and this). Also, you can set height instead of setting width.
It would be useful for responsive design in a way, and I think it's really tricky!
Note: It doesn't work with flex-boxes, if you set the parent's width or height. In this case, you must explicitly set width and height, or there would be another tricks for that; flex-boxes works completely different.
The most complex stuffs are hidden in the simplest!
What they mean to me by this sentence is to «take care of scalability».
And for that, there is nothing better than svg. We need to think about caching. Just avoid to embed them directly. Let the client browser do the caching by using external src.
As soon as this is well done, we can scale it at moon size, keeping it smooth...
Svg can be generated server side, but it's always better to carefully create them with (gimp). Then open the svg with a text editor.
If using images, currently, for nice rendering in different screen resolution, the best should be to use a set of them in different resolution, with srcset. Finally just like other dynamics elements, let the client browser do the choice by providing him many options. Again, with caching in mind. it will download and keep only the one it need.
If an html solution exist, we should use it before trying to alter it (by js or css).
https://css-tricks.com/responsive-images-css/
A new css property is in town: image-rendering.
https://drafts.csswg.org/css-images-3/#the-image-rendering
As usual, the most complete answer are the specs!
https://drafts.csswg.org/css-images-3
I'm trying to change images when doing mouseover/mouseleave using CSS or SASS. However, to acomplish this I can always do:
header = panel.getHeader().getEl();
and then do this:
//mouse enter event
header.on('mouseover', function (e) {
.......
.......
}, me);
//mouseleave event
header.on('mouseleave', function (e) {
........
}, me);
However, I'm trying to accomplish the same functionality using CSS or SASS.
Basically:
a) All images should be displayed by default when loading the accordion. (Image 1 should be displayed for panel 1).
b) If panel is expanded Image 2 should be displayed and is its collapsed Image 1 should be displayed (on panel 1 - same functionality for the other panels).
c) On mouseover Image 2 should be displayed and on mouseleave Image 1
should be displayed (on panel 1).
This is the CSS I'm using so far and it works on the first panel when doing a mouseover/mouseleave, but I'm not really sure how to get the images to be displayed.
// Show IMAGE 1 by default
.x-panel-header-custom1{
url('http://www.iconhot.com/icon/png/brush-intense-messenger/256/msn-web-
2.png');
}
// SHOW IMAGE 2 when expanded or onmouseover
.x-panel-header-custom1:hover{
background: red;
background-image:
url('https://image.flaticon.com/icons/png/128/12/12195.png');
}
Can anyone tell me what i'm missing?
Here's the working FIDDLE
Note: I don't want to use Font awesome for the images, any other
images are fine like the ones I'm using. Thanks a lot in advance!
Line comments are not valid in CSS (Block comments are) - you actually had me questioning my sanity until I spotted this.
When removing the troublesome line comments, if you look into the html, you clearly see
.x-accordion-item .x-accordion-hd
selector overwriting the
.x-panel-header-custom1
selector, and therefore you must use !important on all your classes, if you want your code to work. Like so:
.x-panel-header-custom1 {
background-image: url('http://www.iconhot.com/icon/png/brush-intense-messenger/256/msn-web-2.png') !important;
}
.x-panel-header-custom1:hover {
background: red;
background-image: url('https://image.flaticon.com/icons/png/128/12/12195.png') !important;
}
.x-panel-header-custom1-collapsed {
background-image: url('https://image.flaticon.com/icons/png/128/12/12195.png') !important;
}
Also, I noticed your third selector ( collapsed one ) was missing the header string.
Fiddle
I am making a computer game on Twine, which accepts html, javascript, css.
I am trying to display images based on the state of the game.
This code below, works correctly i shows all 3 images overlapping correctly.
However, i want to display other images based on game state. For example if the player is at 20% health, it should display 2a.pgn instead of 2.pgn
or if it is poisoned, it should show 3a.pgn instead of 3.
And so on and so on, it does not make sense having to specify all possible combinations. Instead i just want to change a single layer at a time based on a variable/switch.
<html>
<div class="a1"></div>
<style>
.a1 {
width: 100%;
height: 1000px;
background-image: url(3.png),url(2.png),url(1.jpg);
background-repeat: no-repeat;}
</style>
</html>
Could you please help?
Thank you very much.
Cheers,
There are multiple ways - setting url() (and preloading everything on load), changing visibility, opacity or z-index, but if you want to stick with multiple backgrounds:
//imageIndex - your image for given HP
//imagesLen - images count
var HPimgArr = Array(imagesLen).fill('-9999px 0');
HPimgArr[imageIndex] = '0 0';
document.querySelector('.a1').style.backgroundPosition = HPimgArr.join(', ')
If you are refering to Javascript try this (you need jQuery for this):
var maxHealth = 10;
var health = 10; //He is apparently at full health
function updateHealth(newHealth){
health = newHealth;
if(health < maxHealth / 5) {
var stats = $('.a1').css('background-image').split(','); //Put every different stat in array
stats[1] = 'url(2a.png)';
$('.a1').css('background-image', stats.toString());
}
}
Whenever you want to change his health call updateHealth(...).
I haven't tested this but something along these lines should work.
I want to change the background color of in-viewport elements (using overflow: scroll)
So here was my first attempt:
http://jsfiddle.net/2YeZG/
As you see, there is a brief flicker of the previous color before the new color is painted. Others have had similar problems.
Following the HTML5 rocks instructions, I tried to introduce requestAnimationFrame to fix this problem to no avail:
http://jsfiddle.net/RETbF/
What am I doing wrong here?
Here is a simpler example showing the same problem: http://jsfiddle.net/HJ9ng/
Filed bug with Chromium here: http://code.google.com/p/chromium/issues/detail?id=151880
if it is only the background color, well why don't you just change the parent background color to red and once it scroll just change it to pink?
I change your CSS to that
#dad
{
overflow-y: scroll;
overflow-x: hidden;
width: 100px;
height: 600px;
background-color:red;
}
I remove some of you Jquery and change it to this
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
});
And I remove this line
iChild.css('backgroundColor', 'red');
But is the Red color it is important that won't work for sure http://jsfiddle.net/2YeZG/5/
I like Manuel's Solution.
But even though I don't get what you're exactly trying to do, I want to point out a few things.
In your fiddle code, I saw that you included Paul Irish's Shim for requestAnimationFrame.
But you never use it.
(It's basically a reliable setTimeOut, nothing else) it's from frame based animations.)
So since you just want to change some CSS properties, I don't see why you would need it. Even if you want transitions, you should rely on CSS transitions.
Other than that your code could look something like
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
eachElemNameHere.css('background-color','randomColor');
});
Also you should ideally not use something like that if you can help it. You should just add and remove class names and add all these properties in your CSS. Makes it work faster.
Also, again I don't quite get it, but you could use the jQuery function to find out each elements' position from the top to have better control.
Your problem seems to be that you only change the background color of the elements which have already been scrolled into view. Your code expects that the browser waits for your code to handle the scroll event before the browser redraws its view. This is most probably not a guarantee given by the HTML spec. That's why it flickers.
What you should do instead is to change the elements which are going to be scrolled into view. This is related to off screen rendering or double buffering as it is called in computer games programming. You build your scene off screen and copy the finished scene to the visible frame buffer.
I modified your first JSFiddle to include a multiplier for the height of the scroll area: http://jsfiddle.net/2YeZG/13/.
dad.bind('scroll', function() {
// new: query multiplier from input field (for demonstration only) and print message
var multiplier = +($("#multiplier")[0].value);
$("#message")[0].innerHTML=(multiplier*100)-100 + "% of screen rendering";
// your original code
var newScrollY = newScrollY = dad.scrollTop();
var isForward = newScrollY > oldScrollY;
var minVal = bSearch(bots, newScrollY, true);
// new: expand covered height by the given multiplier
// multiplier = 1 is similar to your code
// multiplier = 2 would be complete off screen rendering
var newScrollYHt = newScrollY + multiplier * dadHeight;
// your original code (continued)
var maxVal;
for (maxVal = minVal; maxVal < botsLen; maxVal++) {
var nxtTopSide = tops[maxVal];
if (nxtTopSide >= newScrollYHt) {
break;
}
}
maxVal = Math.min(maxVal, botsLen);
$(dadKids.slice(minVal, maxVal)).css('background', 'pink');
});
Your code had a multiplier of 1, meaning that you update the elements which are currently visible (100% of scroll area height). If you set the multiplier to 2, you get complete off screen updates for all your elements. The browser updates enough elements to the new background color so that even a 100% scroll would show updated elements. Since the browser seldom scrolls 100% of the area in one step (depends of the operating system and the scroll method!), it may be sufficient to reduce the multiplier to e.g. 1.5 (meaning 50% off screen rendering). On my machine (Google Chrome, Mac OS X with touch pad) I cannot produce any flicker if the multiplier is 1.7 or above.
BTW: If you do something more complicated than just changing the background color, you should not do it again and again. Instead you should check whether the element has already been updated and perform the change only afterwards.