HTML5 has a flaw with regard to responsive sites with images - css

I am currently working on building a responsive site but have come across a strange flaw with HTML 5.
There is no longer going to be support for sizing images at 100%, and also background images. You can now ONLY specify an image size by pixels. So if you have an image in a column or grid system, and that column or grid is sized in % as most are, the image will just fall back to its original size. This is fine if we are willing to only use images at the maximum resolution for the biggest media size.
This is fundamental kick in the teeth to responsive sites. I have looked around the web at responsive solutions and it seems that even systems like pure.css have ignored the flaw and put massive images in that work fine on full hd but take ages to load. This is a major problem when dealing with responsive sites as images by nature will now have to be output at full anticipated resolution. Imagine when 4hd becomes the norm, all responsive sites will require compressed jpegs of around 8mb in size just to work. Even for tiny icons, if they are intended to grow or shrink in scale.
The flaw has however been picked up by browsers which for now still support 100% image width but only when styled inline - for how long?
Below is an example where I would normally set an img to be wrapped by a container that makes the image fit 100% of the space given to it whilst retaining its ratio:
.photo-box img {
max-width: 100%;
height: auto;
}
In HTML 5 this no longer works. The image will only show at its maximum resolution. However if you force 100% into inline like so
<img src="images/pics/articles/article_127.jpg" alt="girl" width="100%"/>
Then this works as intended too. But this is not html 5 compliant. see Differences Between HTML 4.01 and HTML5 [http://www.w3schools.com/tags/att_img_width.asp][1]
Now I know a few of you will say - well, why size an image using percentage? But there is always a need for it with responsive sites, and there will be greater need for it when larger media types become available. Don't forget that percentage works both ways to make an image larger but also it is handy to resize an image smaller too without the need for any jquery or similar API or other clientside scripting. When an image gets smaller without % it can lose its ratio when the width has a constricting percentage container or parent. Only width 100% and height auto can stop this from happening.
Now back to the same issue with background images - A common use for background images is to apply rounded corners and shadow effects to an image but to overlay that background with an img tag of the same source with opacity set to 0. This is used all over the web to get around the fact that you can't style shadows or corners consistently to an img tag. Only its container can be styled with such effects and the images square corners overlap them. Now that 100% width is no longer supported this effect will not work as the image in the background cannot resize to match a responsive img above it and so the background tiles even if the repeat is set to none, which looks bad.
Does anyone have the same issue or know of the solution. Can anyone specify who we need to mention this to with the aim to get it back in to HTML5?

You confused the attribute (<img width="" />) width with the CSS property width (img { width: ... ; }) which are not the same.
Here is a better source:http://www.w3.org/wiki/HTML/Elements/img and here a possible duplicate of this post: What's the difference between HTML's and CSS's width attribute?
About the attribute width=""
width = non-negative integer
Give the width of the visual content of the element, in CSS pixels.
About the CSS Property width:; http://www.w3.org/wiki/CSS/Properties/width
Values <length> | <percentage> | auto | inherit
Initial value auto
Applies to All elements but non-replaced inline elements, table rows, and row groups
So you are safe to use CSS width property with percentage but not within the attribute.
If you want to give an image an inline width of 100%, you may do it like this:
<img style="width: 100%;" />
Regarding your question.
if your HTML is this:
<div class="photo-box">
<img src="images/pics/articles/article_127.jpg" alt="girl" width="100%"/>
</div>
with this selector:
.photo-box img {
width: 100%;
height: auto;
}
It is very much likely that the attribute overrides the CSS property. Remove the property for your tests or try (but don't use this all the time, just for testing)
.photo-box img {
width: 100% !important;
height: auto;
}

With some valid pointers from nico it seems I have a solution at least to applying styles to images. I am now using the background source inline and I have changed photo-box to image-box. I am also now able to apply any, none or all styles to the images:
my html is as follows which will draw three images whose containers are 100% wide at all times and have the desired effects applied:
example 1 - just the wrapper
<div class="image-box" style="background-image:url(images/example_123.jpg)">
<img class="image-hide" src="images/example_123.jpg" alt="image example"/>
</div>
example 2 - the wrapper with the shadows and highlights
<div class="image-box image-effect" style="background-image:url(images/example_123.jpg)">
<img class="image-hide" src="images/example_123.jpg" alt="image example"/>
</div>
example 3 - the wrapper with corners
<div class="image-box image-radius" style="background-image:url(images/example_123.jpg)">
<img class="image-hide" src="images/example_123.jpg" alt="image example"/>
</div>
example 4 - the wrapper with all
<div class="image-box image-radius image-effect" style="background-image:url(images/example_123.jpg)">
<img class="image-hide" src="images/example_123.jpg" alt="image example"/>
</div>
my css is as follows which now works as pointed out by nico, and includes display:block (avoids the 4px height issue) and width:100% (which avoids the inline size issue with html5)
/*image div wrap for using background under image (applied to container of background)*/
.image-box {
background-repeat: no-repeat;
background-size:contain;
background-position: center center;
}
/*image div wrap for effect (applied to container of background when shadow required)*/
.image-effect {
box-shadow: -4px 4px 8px 0px rgba(0, 0, 0, 0.3), inset -3px 3px 5px 0px rgba(255, 255, 255, 0.6), inset 3px -3px 5px 0px rgba(0, 0, 0, 0.6);
}
/*image div wrap for corner (applied to container of background when corners required)*/
.image-radius {
border-radius: 16px;
}
/*img class (to prevent the square edge of the actual image from hiding the style*/
.image-hide {
opacity: 0;
}
/* img tag when inside image-box (to prevent the addition of 4 pixels when default inline and to set the image width to fit the container always in aspect ratio)*/
.image-box img {
height: auto;
display: block;
width:100%;
}

You aren't setting width in CSS you mentioned - change max-width to width

Related

Resize an image using calc() css

I'm trying to resize any image with existing height and width properties by a percentage (and keep proportions). I know that transform: scale(1.05) would take an image that's 100px by 100px and make it 105px by 105px, but it would still only occupy the original 100x100 space in page flow.
How would I do something like:
<img src="an.svg" width="100" height="100" alt="bigger please" class="resize" data-width="100" data-height="100"/>
img.resize {
height: auto;
width: calc(original width * 5%);
}
So that the browser renders an image that's 105px by 105px and that occupies the full 105x105?
I'm using simplified numbers for this question, but the images could have any value for either dimension.
Additionally, I can not use a wrapper or a background image, but I do have access to data-height and data-width attributes present on the images. Codepen is here: https://codepen.io/spicedham/pen/qMKLYq
Assuming you have a container available that the image is placed in, you can easily use calc to get the height and width for the image
check out this pen to see an example.
https://codepen.io/calebswank11/pen/gdKBRE
.container {
width: 300px;
height: 300px;
}
img {
display: block;
width: calc(100% + 5%);
height: calc(100% + 5%);
left: -2.5%;
top:-2.5%;
position: relative;
}
I don't think you can use the width/height attribute of an image to define new width/height. You can probably consider inline styles and CSS variable like this:
img {
width:calc((var(--width) * 5/100 + var(--width))*1px);
height:auto;
}
<img src="https://picsum.photos/100/100?image=1069" height="100" >
<br>
<img src="https://picsum.photos/100/100?image=1069" height="100" style="--width:100">
If it's not totally necessary for the img tag to be utilized (and the image is always the same aspect ratio if it's dynamic) then you could use a div with a background image, and give it height: 0; and padding-bottom: 100% (or whatever percentage that would create the appropriate aspect ratio) and modify it that way with css transforms
After exhaustively trying every permutation I could think of, I do have a solution of sorts. It requires two things I was trying to avoid (a container & inline styles), but it works as part of a system. Some additional background: I work on a web app that lets users set a base font size (think 12, 14, 16, or 18pt) and then also handles zooming at on top of that with a range from a 10% to 300% for low vision users. We have some images (mostly math expressions) that are embedded within the surrounding page content as SVGs. At default print and zoom levels an SVG with the number '3' in it is the same size as plain text number 3 next to it. But things get mismatched as the other variables start to change. The technique described below, once in place, will let us have fine-grained control over how these images match up with surrounding text regardless of print size or zoom level.
Here's a link to solution in codepen https://codepen.io/spicedham/pen/pxzYYe and a variation using... variables https://codepen.io/spicedham/pen/MPgxxo.
Here's the CSS:
.container {
display: inline-flex;
vertical-align: middle;
border-left: solid .05em transparent;
border-right: solid .05em transparent;
}
.scaleMe {
transform: scale(1.1);
margin: .05em 0;
}
And here's the what the images and containers look like:
<span class="container" style="font-size: 300px;"><img class="scaleMe" src="svg.svg" width="300" height="100" alt="" style="font-size: 100px"/></span>
<span class="container" style="font-size: 100px"><img class="scaleMe" src="svg.svg" width="100" height="200" alt="" style="font-size: 200px"/></span>
The problem I ran into whether I used calc() or transform:scale() was that I could not get content to reflow around the resized image consistently - an image scaled up would overlap adjacent content. It was possible if all the images were the same size or they all had the same proportions, but that's not something I can count on in our system.
The other problem was that using percentages as units, while the logical choice, does not work as you'd expect.
So the solution was to create a stand-in relative unit of em. I took the width of the image (say 300px) and set it as the font size for the container. I then took the height of the image (say 100px) and set it as the font size of the image. This allows me to prop open the container to occupy the same space as the scaled image. Gets around the limitation of not being able to use percentages for border widths and accurately set the equivalent of a percentage for top and bottom margins on the image.

How can I center an <img> inside a div and have it scale with the div's height?

I'm using centered imgs to act as backgrounds for some tiles. I'm trying to have these images scale with their parent div's height and if they are wider then their parent's for them to hide the overflow.
Example:
* I've got it working now. Answers are below, I'm updating this code to display all I needed to use to get it to work *
HTML
<div class="container">
<img class="derp" src="http://gridiculo.us/images/kitty02.jpg">
</div>
CSS:
.container {
height:250px;
width:50%;
}
.derp{
object-fit: cover;
height: 100%;
width: 100%;
}
Here's a near-example: http://codepen.io/chriscoyier/pen/myPMGB
The difference would be that I'm using s and not background-image, and that instead of the img filling the div completely it would fit to the height and hide the width overflow.
I'm trying to avoid using background-image since I'm using a lot of these tiles and making CSS rules for every one isn't going to work.
In order to scale it with the div's height, I'd change the height from px to % - this way, the larger's the div, the larger's the picture. In order to certain the image, i'd use margin in the image css. That'd look like so:
.derp{
height:80%;
width:80%;
margin:10%;
}
.container {
height:250px;
width:50%; /* needed */
/* inner img is centered horizontally */
vertical-align:top;
text-align:center;
overflow-x:hidden;
}
<div class="container" style="background-color:gray"> <!-- The background is there so you could see the image relative to the div -->
<img class="derp" src="http://gridiculo.us/images/kitty02.jpg">
</div>
The best way to keep the aspect ratio of the image is to set the width to auto (and it's the default behavior so you don't need to set explicitly). And with a simple overflow:hidden it works almost as you want it.
The hard part is centering horizontally. You can try this answer :css to center a image horizontally.
However if all your images aren't the same size, you will need to make one rule per image. And in this case putting the image as background-img would be better for semantic and accessibility (because your image doesn't have a sense in the page, it doesn't convey any information, it's decoration). An <img> would be read by a screen reader (the alt attribute), and in your case it wouldn't help a blind people.
Depending on how many browsers you need to support, I'd suggest you use object-fit! Support for it is okay if you can ignore IE, but in case your project qualifies, I see no problem with using it today. Also, there is always a polyfill.
You can find a nice summary on CSS-Tricks.com about the property. It basically works similarly to background-size, but for <img> tags. In your case, object-fit: cover; does the trick.
I made a little demo on CodePen that shows you how it works.
img {
height: 100%;
object-fit: fill;
width: 100%;
}

Bootstrap carousel - how to use an image as background that is LARGER than the carousel?

I've been beating myself this weekend to get around this one.
I have a site that uses Bootstrap 3.0 and a Carousel with background images, and I've managed to reproduce my question in a small fiddle.
I have a max-heighted div with an image inside. The image will typically be larger than the div (at least in height). I'm using the img-responsive class from bootstrap to make sure that in mobile browsers the image scales down. That is the reason why I max-height the div and don't put a fixed height on it.
My questions is: how can I get the image to vertically align to the middle?
I've tried:
Adding classes display: table and display: table-cell, but a table cell cannot have a max-height.
Aligning things vertically but none seem to work.
Setting a negative margin on the image using javascript, but that makes the div smaller as well as the div uses the image to size itself.
Using css background instead of an inline image. This does not make the div be (at most) as large as the image and doesn't allow responsive growing/shrinking.
Fiddle: http://jsfiddle.net/SabbeRubbish/dZQ26/4/
<div class="carousel-inner">
<div id="frame" class="item active">
<img src="https://www.google.com/images/srpr/logo11w.png"
class="img-responsive" />
</div>
</div>
Can anyone recommend me good and clean ways to get the image to center vertically? Or tell me what the hell I'm doing wrong? :-)
Thanks.
PS: why center vertically? If the page is very wide, there is a large clip area as the image grows with the page. It is nicer to show the middle of the picture rather than the top.
is this something closer to what you are trying to achieve ?
#frame {
border: 1px solid grey;
max-height: 100px;
min-height: 100px; /* Remove this line */
padding: 15px 0px; /* Add this line to always have height on the div */
background-size: cover;
background-image: url(https://www.google.com/images/srpr/logo11w.png);
background-position: center center;
}
http://jsfiddle.net/rrEYJ/
EDIT:
As suggested in the comments you can also use background-size: contain; to have the entire image inside the #frame element. You will probably have to also use background-repeat: no-repeat; in that case.
Check this fiddle: http://jsfiddle.net/rrEYJ/1/
EDIT2:
Based on your comment I did some research and apparently the background-size property can be set in percentages also. Based on this new information see this fiddle:
http://jsfiddle.net/rrEYJ/3/
EDIT3:
The css had a min-height property that's why the div wasn't changing it's height. Check this fiddle: http://jsfiddle.net/rrEYJ/4/
I hope this helps.
Add style for image like this
#frame img {
width:auto;
max-height:100px; }

How to get a background image to extend full width when using a grid?

Is it possible to have a wrapper element's background image extend beyond the grid while keeping things responsive?
I am able to do it with a solid color using the box shadow technique, but I haven't been able to get the background image to break out of the grid.
I'm using a 12 column flexible, percentage based grid that has a max width of 1140px and floats the columns. Setting the background image of the wrapping element ends up at 1140px unless I gave the element an absolute width (like 150%) which breaks the responsiveness and I'm pretty sure is bad practice anyway.
My layout is simple, something like this
<body>
<container>
<header></header>
<inner-content>
<grid-element-one></div>
<bg-wrap>
<grid-element-two></div>
</div>
<grid-element-three></div>
</inner-content>
<footer></footer>
</container>
</body>
And it's laid out where the element that I need to have the background-image is in between other gridded sections. So I can't just put it above the footer or something and have the grid end before it's affected.
The css is also bare bones.
.inner-content {
max-width: 1140px; /* when 768px+, otherwise 96% */
}
.element-two {
color: $font-color;
background-color: $bg-gray;
box-shadow: -25rem 0 0 $bg-gray, 25rem 0 0 $bg-gray;
height: 475px;
}
.bg-wrap {
background: url(../images/bg/texture.png) 0 80px repeat;
}
Is this what you want ? http://jsfiddle.net/mPGQQ/7/
If yes you have to move the end of your div class="inner-content" to the end, and modify the css for .inner-content as in the fiddle.
Hope this helps
Cheers

Scaling generated content in CSS

How do you scale an image added in :before or :after in CSS?
For example, I have a page which contains a book cover:
<span class="book">
<img src="http://ecx.images-amazon.com/images/I/41t7xMPK%2B6L.jpg" />
</span>
I want to use CSS to make it look more like a book, rather than just a cover. I can use :before to add a second image to do this, but as all books vary in size, I need to be able to scale this image to fit the book cover.
I have tried
.book:before{
content:url("/images/book.png");
position:absolute;
height:100%;
width:100%;
}
but this doesn't work in scaling the image.
you can scale it:
transform: scale(0.7);
but it won't work with px or %.
The generated image is always displayed 1:1. You cannot scale it. When you fix the size of the generated element, that works well. You could check it with the following CSS attributes:
#logo-image:before
{
display: block;
content: url(img/logo.png);
width: 300px;
height: 100px;
border: solid 1px red;
overflow: scroll; /* alternative: hidden */
}
You can see the red border at the specified size, and the image content is clipped. But if you leave out the overflow:scroll, you will see the image exceeding its element.
(Tested on Firefox 11)
Try setting a min-height and a max-height for both of them to the same value, It should then scale the images to the correct size while keeping the correct aspect ratio. (And do that with the width, depending on which one you want to scale)

Resources