How to crop and resize in the browser - css

I like to do a client side crop and resize of an image before displaying it in HTML 5. (The actual react application will allow to select a part of a bigger image that is displayed in a fixed size image window)
I know the offsets in pixels (x and y) in the source image and the scaling factors for width and height needed.
I can easily crop (without scaling)
<div style="overflow:hidden; width:300; height:300;">
<div style="display: inline-block; background: url('test.png') no-repeat; background-position: -10px, -10px;" />
</div>
Scaling works, but cropping get's corrupted when I include scaling
<div style="overflow:hidden; width:300; height:300;">
<div style="display: inline-block; background: url('test.png') no-repeat; background-position: -10px, -10px; transform: scale(10, 10);" />
</div>

CSS clip-path is a pretty versatile CSS property that does exactly what it sounds like you need to do. It can get lengthy, however, so I highly recommend moving to an external stylesheet as opposed to doing this inline.
What I would suggest is that you set the image in a fixed-size container, as you stated, set overflow: hidden; (of course), and crop the image with clip-path. For resizing it, use transform: scale() with one parameter, depending on how much you need to scale it.
Keep in mind that another rule could also be used like CSS object-fit.

I found the following solution
<div style="overflow: hidden; width: 300px; height: 300px;">
<img src="test.png" style="width: 600px; height: 600px; transform: translateX(-300px) translateY(-300px);">
</div>
The important aspects are:
Have a size limiting container (the div) with overflow: hidden
Resize the complete image by scaling the width and height
Crop the needed parts from the resized image (with transform translateX translateY)

Related

Forcing Image to fill a Div in Angular regardless of aspect ratio

I want to display a bunch of images stored on a server. The images are taken from a user's phone and the dimensions and aspect ratio are unknown.
I just want to have an image fully fill a DIV while maintaining its aspect ratio. If the image is wider than taller, I want the image scaled so the height is 100% the Div and the sides would be clipped off. Similarly for if the image is taller than wider, I want the image scaled up/down so the width is 100% of the Div
Hopefully this explains it
I thought this would be pretty trivial, but here i am. I can make an image fit tall or wide but not either depending on the aspect ratio. I've tried several different methods and I am at a loss.
I have a Stackblitz Example here.
I have a 2x2 grid, and I would like to get the images to fill those grids. Some images need to be rotated. I'm not sure why they need to be as the look normal on my computer. I have a hardcoded flag to force a rotation on some images, but the rotation appears to screw up the css further on.
CSS:
.img-container {
/* height: 150px; */
width: 100%;
}
.img-container img {
height: 100%;
/* height: -webkit-fill-available; */
width: 100%;
object-fit: cover;
}
HTML:
<div class="showBorder img-container">
<img #image class="container-img-objfit2"
[ngClass]="{rotateLeft: rotate}"
[src]="imageURL" />
</div>
How can I fill these DIVs regardless of the aspect ratio?
Can I do any of this inside angular? I tried to get the image size and see if I could set custom class that would handle the rotation, but that didn't seem to work either. The dimension for all my pictures was identical. So no way to distinguish which pictures need rotation.
Or am I going about this all wrong? Ultimately I think I will have a process to scale and crop the images on the server so they are prepared for the client app.
Update:
This sample is an attempt to set the image in the background and use a :before selector to rotate the image. It does not work fully as I cannot change the image dynamically to other images.
You can just set the images as background-image for the div and set its size to cover.
So just remove the img tag and keep your div tag only
<div class="showBorder img-container" [style.backgroundImage]="'url(' + imageURL + ' )'">
</div>
In CSS you will have to specify the height and the size
.img-container {
height: 150px;
width: 100%;
background-size:cover;
}

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.

Wordpress/CSS - picture doesn't show up

The first thing I'd like to point out is that I know almost nothing about CSS. At the moment I'm trying to create a website using Wordpress and I want to add an image that acts like a link and which changes to another image when the mouse is hovering over it.
I found following tutorial for this: https://www.organicweb.com.au/17523/wordpress/image-link-css/
I've done exactly what this tutorial says (basically it's more or less just copy & paste), but my image won't show up and I have absolutely no idea why. Even stranger is that the image does show up when I use a definite image size in the stylesheet (for example: "width: 300px; heigth: 250px;"). But it doesn't work when I use "background-size: cover;", "background-size: contain;", "background-size: auto;" or any other possibility.
This works:
.ge-link {
background-image: url(http://.../wp-content/uploads/2017/02/325484_1280.jpg);
background-repeat: no-repeat;
background-position: center;
width: 300px;
hight: 250px;
display: block;
This doesn't work:
.ge-link {
background-image: url(http://.../uploads/2017/02/325484_1280.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
display: block;
Does anyone have an idea what I might be doing wrong?
what I guess you could do is to have both images together in your html and use :hover to show a different image once the main image is hovered:
HTML
<a id="linkId" href="www.yourlink">
<img class="image_on" src="yourFirstImage.png" alt="picture">
<img class="image_off" src="yourSeconfImage" alt="picture 2">
</a>
CSS
.image_off, .link-block:hover .image_on{
display:none
}
.image_on, .link-block:hover .image_off{
display:block
}
.ge-link is not an image tag, it's just a container that has a background image. In the second case, you didn't define a height for that container (also no width, but that's not the primary cause for your problem), so that container is 0 pixels high - no heigth! It actually contains the background image, but with 0 heigth it doesn't show anything.
So just use those width and especially height settings as long as you use the image as a background image. Or use a real image element (<img>).
P.S.: You can use the width/height settings and background-size: cover - works perfectly...

Background images outside of <body>?

I am attempting to position a background image so that it lines up with an existing gradient background, which is relatively positioned to the <html> element (ie. the gradient image appears at 92% of the browser width, no matter how you size the window).
I did it by placing the image inside a <div>, positioning the image relative to the <div>, and positioning the <div> relative to the browser window.
eg.
<body>
<div id="background-position-container">
<img src="images/bubbles.png" id="background-corner-decoration" />
</div>
</body>
with:
<style>
#background-position-container {
position: absolute;
width: 0px;
height: 0px;
top: 180px;
left: 92%;
}
#background-corner-decoration {
position: relative;
/* tweak the position of the image so it lines up with the gradient */
top: -176px;
left: -118px;
width: 216px;
height: 477px;
margin: 0px -118px -176px 0px;
}
</style>
This seems to work well, but if you shrink the browser window horizontally, the background image will cause the <body> element to grow beyond the <html>element, and scrollbars appear.
I seem to be able to fix this by creating a new sibling element of <body> and placing the <div> inside that:
<div id="background-page-container">
<div id="background-position-container">
<img src="images/bubbles.png" id="background-corner-decoration" />
</div>
</div>
<body>
</body>
and adding:
#background-page-container {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
overflow: hidden;
}
This works in Firefox at least, but this does not seem like a good practice and I'm sure all browsers do not render this properly. Is there a better way to accomplish what I want while leaving all display elements inside <body> (That is, having the background image clipped at the edge of <body> instead of growing it)?
Thanks for your help,
gs.
Edit: As requested, here are jsfiddles to illustrate the problem:
Here is what it looks like with Hiigaran's solution: http://jsfiddle.net/kn36A/
Here is a solution that aligns properly, but causes unsightly scrollbars when the window is re-sized: http://jsfiddle.net/w446Q/
Here is the "best" (?) solution I have so far, but it seems to violate HTML best-practices: http://jsfiddle.net/H2PLr/
Every browser I have tested #3 with seems to render it properly so far - is this solution really as bad as I think it is?
Thanks again!
gs.
Assuming I read correctly...
You can combine background CSS by separating them with commas. So for instance, if you want to have an image and a gradient as the background for the same thing, try:
background-image: url('image.png'), linear-gradient(#bb0000, #0000bb);
You can then add other background CSS properties like background-position in the same manner:
background-position:50px 50px, 0;
The order of the values matters. The first set of values (50px 50px) applies to the image, but not to the gradient. The second background-position value (0) applies to the second background-image value, which is the gradient.
Using this on your HTML, you should be able to position your image with absolute or relatively values.
EDIT: Also, if you add any additional background property without commas, then the value you provide will apply to all backgrounds. For example, background-repeat:no-repeat will not repeat either the image or the gradient, but background-repeat:no-repeat,repeat will be applied to each in the same way that the position values are.
In the comments of the other answer Hiigaran solved the problem by simply starting with solution #3 and moving the outer containing div (called "background-page-container") under <body>. So there's no need for elements to appear outside of <body> as I had thought.
gs.

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

Resources