howto crop *AND* scale a background image in css - html

I have a "main-image" containing lots of small images which I "clip" into divs of fixed size by setting the background-position to some negative offsets. This works great!
Now I have a div with a size that changes during the lifetime of the web-page.
The old code had its own backgound-image with the background-size set to "contain". Something like this:
.dump {
display: inline-block;
background-image: url("/some/image.png");
background-repeat: no-repeat;
background-size: contain;
}
And that worked great too.
Now I'm trying to clip that background image from my "main-image".
E.g. My "main-image" has a size 1800px128px
The sub-image I like as background starts #1200px,10px with a size of 200px x 80px.
Is there a way to clip this rectangle and than scale to the dimensions of the containing div (which are unknown at the time of programming)
Thanks for the hint. However, I tried but can't get anything to work:
My problem is, that the div image should follow the height the containing div, so I can't tell size, or scale or zoom or whatever at the time of coding. I give an example:
<div style="width:100%; height:30%; text-align: center">
<div class="dump"></div>
</div>
Now, as I said: The image I want to appear as the background of div.dump is the 200x80px area from the main-image #origin(1200,10) AND I want that resulting image scaled to fit the hight of the container. So, I have a known translation, followed by an unknown zoom. Maybe it's just over my head.

I believe the best way to do this is using css transforms, I found this page for further reference on how to transform a background image and made this fiddle based on it.
The idea is that you will use the classes "icon" and "icon:before" to configure your sprite to fit in an element and use other classes like "smaller" and "bigger" to set the actual size of the element.
.icon
{
font-size: 2em;
text-align: center;
line-height: 3em;
border: 2px solid #666;
border-radius: 7px;
position: relative;
overflow: hidden;
}
.icon:before
{
content: "";
position: absolute;
width: 100%;
height: 100%;
left: 0%;
top: 0%;
z-index: -1;
background: url(http://blogs.sitepointstatic.com/examples/tech/background-transform/background.png) 0 0 repeat;
transform: translate(-50%, -50%) scale(1.5, 1.5);
background-repeat: no-repeat;
background-size: contain;
}
.smaller{
float:left;
width: 120px;
height: 120px;
}
.bigger{
float:left;
width: 200px;
height: 200px;
}
Because css transforms support percentage, the background will be clipped and scaled correctly, according to the size defined in "smaller" and "bigger"

Related

Scale flex box height to fit image div

I am building a chat message and I want to fit an image inside the text bubble. The bubble has a fixed width and should scale its height depending on the image aspect ratio.
I am unable to scale the div to maintain the img aspect ratio. All of the answers found use an <img> tag, while I am using a div and none of that fixed my issue.
This is the desired outcome:
What I have achieved instead is either a very small img (size of an empty speech bubble if I do not impose any vertical or horizontal dimension) or a long img if I impose the width and keep the height dynamic.
.speech-right-wrapper {
max-width: 90%;
display: flex;
flex-direction: column;
}
speech-right-message-container {
display: flex;
justify-content: flex-end;
align-items: flex-start;
}
.speech-right-bubble {
position: relative;
background: rgb(154, 226, 255);
box-shadow: 0px 1px 2px gray;
border-radius: 15px 0 15px 15px;
display: flex;
}
.bubble-background {
width: 200px;
height: auto;
overflow: hidden;
}
.bubble-background-img {
position: absolute;
border-radius: 15px 0 15px 15px;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
background: no-repeat;
background-size: cover;
background-position: center;
}
<div class="speech-right-wrapper">
<div class="speech-right-message-container">
...
<div class="speech-right-bubble">
<div class="bubble-background">
<div class="bubble-background-img" v-bind:style="{ 'background-image': 'url(' + require('../assets/img/profiles/' + storyPath + bubble.bubble_background) + ')' }" v-bind:alt="bubble.bubble_background"></div>
</div>
...
</div>
...
</div>
</div>
UPDATE
For clarity, I need the <div class="bubble-background-img"> to be fix in width (say 200px) and height: auto to maintain the image aspect ratio; and I need the <div class="speech-right-bubble"> to scale to fit the image inside.
Also, unfortunately I need to use a <div> tag because v-bind:src seems not to work for local images. If I do:
<img class="bubble-background-img" v-bind:src="'../assets/img/profiles/' + storyPath + bubble.bubble_background"/>
I get this:
You should probably find a workaround for your v-bind:src issue since the correct way to display a content image is via the HTML img element.
That said, there is a solution, but it relies on using the CSS content property for element replacement, which is a fairly recent technology that's apparently still not supported in Microsoft Edge. The following CSS code is the gist of it and worked for me in testing in Firefox 68:
div { content: ('image.jpeg'); max-width: 200px; }
(In theory, a variation of this technique should also work with the more backward-compatible CSS ::before and ::after pseudo-elements, but the image inexplicably doesn't scale in my testing. I didn't spend much time experimenting though.)
I'm not a hundred percent certain what you are going for, but you could try setting the background-size as a percentage?
background-size: 100%;
background-position: center center;
Using a percentage in background size lets you scale one or more axis according to the parent container. (e.g. background-size: 100% 100%; would scale width and height, and give an effect equivalent to the contain value).
Would that work?
(Personally, I would load the image using an element as that's what they are there for, and you could use object-fit as appropriate, but obviously depends on how you've architected the view...)

Image rounded corners issue with object-fit: contain

I want to show an image with rounded corners. So the image must stretch to the container but doesn't crop any part, like object-fit: contain. However, border-radius applies to image element, not the picture content. Here is an example (also JSFiddle):
body {
width: 100vw;
height: 100vh;
margin: 0;
}
div {
width: 100%;
height: 100%;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 20%;
}
<div>
<img src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg">
</div>
You can check how it works when you resize the viewport.
So, is there a way to make the image element resize it's borders in both directions to adjust to the container, just like object-fit does?
Or maybe a way to apply a "crop-by-rounded-rect filter" on the image content?
I've also had this problem and I've found a way to do it. If you set the height and width to auto the img element maintains its aspect ratio and the image touches the borders. You can then use max-width and max-height instead of width and height.
img {
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 20%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
You may also have to center the img on the parent div as now if it's smaller than the maximum size it will move to the top left.
After some research it seems like this is not possible in pure CSS. The answer here also confirms that.
In the other answer of this question the image view is not growing to "touch" the parent container thus leaving empty area around it in all 4 directions and staying small somewhere centered in the container. Which means it doesn't behave the same way, as the code in the question with img element taking the whole parent area and then picture content "stretched" to touch the closest borders with object-fit: contain.
Here is a solution that will fit the image when the container is smaller:
div {
display: flex;
align-items: center;
justify-content: center;
}
img {
border-radius: 16px;
max-width: 100%;
max-height: 100%;
}
If the container is bigger than the image it will just center it. Note that you probably don't wanna stretch the image at this point or it will look bad

Positioning to specific element on parent background

I want to make a device-independent animation in HTML5/CSS3. That means I have a background image, specifically drawn so that its edges can be cut off, and I am using it in a div element with background-size: cover, like this:
#main-image {
background: url(intro1-1.jpg) no-repeat center center fixed;
background-size: cover;
height: 100%;
width: 100%;
overflow: hidden;
z-index: 0;
}
#propeller {
background: url(propeller2.png) no-repeat;
position: relative;
top: 265px;
left: 1080px;
z-index: 10;
background-size: 100% 100%;
width: 18%;
height: 12%;
}
<div id="main-image"><div id="propeller"></div></div>
On top of the background layer, I want to draw the animating layer. Here comes the trouble: how do I position the transparent animating parts to a specific position in the full (non-scaled) background image?
I'd also need to scale the animation layer using the same ratio as the background was scaled. But how do I do that?
SO in effect, I'm looking for a way to load the HD background image, define the HD animating layer on top of it, and then apply the cover to fill the full browser screen.
What is the simplest way to do this?
In my experience this is hard to do in pure CSS. I've made something similar to what you're asking here: http://jsfiddle.net/ahhcE/
Here's the propeller specific code:
#propeller {
background: url(propeller2.png) no-repeat;
background-color: blue;
position: absolute;
top: 50%;
left: 50%;
margin-left: -9%;
margin-top: -6%;
z-index: 10;
background-size: 100% 100%;
width: 18%;
height: 12%;
}
I positioned it absolute just for ease, but you're likely going to want it relative if it's positioned relative to the parent div.
(sorry for the colors, my replacement for your images)
The problem is that on the top margin, and height percentages, the browser inherits those values from the width of the window. So you'll notice that if you resize the view window the box doesn't stay perfectly centered. I've usually solved this in the past using javascript. Something like this:
function heightAdjust() {
var windowHeight = $(window).height();
totalMenuHeight = $("#menu").height();
document.getElementById('menu').style.marginTop = windowHeight / 2 - totalMenuHeight / 2 + 'px';
$('.thing').css("height", windowHeight+'px');
}
Hopefully that helps. Centering vertically is really your only issue here, you can also hack this successfully using table styling which is what a few sites use for vertical positioning. More on that, and other solutions here: http://coding.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/

Text vertically and horizontally centered over a responsive image

I'm looking to center text both vertically and horizontally over an image that grows when the page gets wider.
I originally had the image set as the background for a div of fixed height, in which case it was relatively easy to center it, but because background images aren't structural, I couldn't set the height to be an automatic function of the width, and I had to toss this option out when I went for a more responsive design.
So I've currently got a div with two elements in it, img and overlay text. The image width is set to 100% of the width of its container, and the height varies accordingly. As a consequence, though, I can't set the overlay text to be postion:absolute and top:80px or something, because the distance from the top will have to vary. And even doing top:25% or whatever doesn't work, because a) if that page width shrinks to squeeze the text, or if there's just more text, the vertical centering is thrown off when there are more/less lines, and b) the percentage is arbitrary -- it's not 50 or something, because that would put the top of the text overlay 50% down the image, when I want the center of the overlay to be there.
I've looked, among other things, at this post, which is definitely close -- but in both solutions, the image height is incapable of resizing, and in the former, the JS loads at page load, but then freezes, so that if I change page width/height, things get out of whack. Ideally, this solution wouldn't involve JS for just that reason (even if it reloaded on every resize, that feels non-ideal), but if that's the only solution, I'll take it.
Also, just for added details/fun, I've set a max-height on the image, because I don't want it to exceed roughly 300px height, even on a cinema display.
Basic fiddle of current attempt here, and identical code below. Any ideas? Thanks!
html
<div class='quotation_div'>
<img src='http://www.mountainprofessor.com/images/mount-ranier-mount-features-2.jpg'>
<div class='overlay'>
<p>Any reasonable amount of text should be able to go here. I want it to be able to center vertically even if it takes up 2 or 3 lines.</p>
</div>
</div>
css
.quotation_div {
position: relative;
display: table;
}
img {
width: 100%;
max-height: 300px;
}
.overlay {
z-index: 99;
width: 70%;
margin-left: 15%;
vertical-align: middle;
position: absolute;
top: 25%; /* Obvious problem, cause it's arbitrary */
}
p {
text-align: center;
color: red;
font-size: 165%;
font-weight: lighter;
line-height: 2;
}
You can use CSS background-size to set the width to 100% and the height will be calculated to maintain aspect ratio.
Here's a fiddle using that technique.
If you want the image as an HTML element then I suggest you set it's position to absolute and use the same method of disply:table-cell to center the overlay:
Here's a fiddle using that method, this one stretches the image because of the max-height.
Please Try the below css for .overlay as in your fiddle
.overlay {
z-index: 99;
width: 70%;
/* height: 100%; */
/* margin-left: 15%; */
/* vertical-align: middle; */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
or this is the updated fiddle link http://jsfiddle.net/hLdbZ/284/
I use this combination:
.CONTAINER {
position: relative;
text-align: center;
}
.TEXT {
text-align: center;
position: absolute;
top: 50%;
left: 0;
right: 0;
}
.IMG {
//for responsive image
width: 100%;
height: auto;
}
I just added to the html
<div align="center"></div>
to surround your existing code to get the image to center
hope that helps

Is it possible to achieve this flexible layout without using JS?

What I'm trying to achieve without using JS can be seen on jsfiddle.net/k2h5b/.
Basically I would like to display two images, both centered, one in background and one in foreground:
Background Image: Should cover the whole window without affecting the aspect ratio, which means that the image will always touch two opposite edges of the window, but the image will be cropped.
Forground Image: Should be inside the window without affecting the aspect ratio, which means the image will be always touch two opposite edges of the window, but the image will not be cropped.
It doesn't matter if it's a <div> or an <img> tag, as long as they are displaying the images.
Asume also that the image sizes are known upfront and can be used in CSS or HTML part.
So my question is: is it possible using only CSS or CSS3?
If it's not possible I will accept the answer that will be as close as possible to my goal.
Examples:
When the background image is cropped from the top and bottom:
When the background image when it's cropped from left and right:
After looking at #Kent Brewster's answer, I think I could achieve all the requirements of OP.
This doesn't have the problem of foreground image being cropped and you can also specify constant margin around the foreground image. Also div is being used instead of img tag, because we are using background images. Here is the link and here is the code:
<div id='bg'></div>
<div id='fg'></div>
#bg {
position: absolute;
height: 100%;
width: 100%;
background-image: url(http://i.imgur.com/iOvxJ.jpg);
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: cover;
}
#fg {
position: absolute;
top: 10px;
left: 10px;
bottom: 10px;
right: 10px;
opacity: .7;
background-image: url(http://i.imgur.com/HP9tp.jpg);
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
}
Try this:
<html>
<style>
body {
margin: 0;
}
#bg {
position: absolute;
height: 100%;
width: 100%;
background: transparent url(bg.jpg) 50% 50% no-repeat;
background-size: cover;
}
#fg {
position: absolute;
height: 90%;
width: 90%;
top: 5%;
left: 5%;
background: transparent url(fg.jpg) 50% 50% no-repeat;
background-size: cover;
opacity: .7;
}
</style>
<body>
<div id="bg"></div>
<div id="fg"></div>
</body>
</html>
If the scaling requirement is flexible, it might work. See http://jsfiddle.net/k2h5b/5/ to see it run.
Yes, it's possible.
Basically I just made the background image the background for the <body> (doesn't have to be the body of course), and then put the image inside that with a small margin.
<body>
<img id='fg' src='http://3.bp.blogspot.com/-OYlUbWqyqog/TeL-gXGx3MI/AAAAAAAAHRc/bdqvvvaeC7c/s1600/bald-eagle3.jpg'></img>
</body>
css:
body {
margin: 0; padding: 0;
overflow: hidden;
background: url('http://wallpaper.zoda.ru/bd/2006/07/21/2c7b4306fd22f049f331d43adb74a5f7.jpg') no-repeat left top;
}
#fg {
margin: 20px 20px;
opacity: 0.7;
}
obviously if the window is too big, there'd be issues. You could (I guess) use media queries to pull in different image sizes based on window size.
edit — OK, well for the image, if you do want it to crop and retain the right aspect ratio, then I think you'll have to know the image size ahead of time to do it so that it works out. Lacking that, here's another revision.
<body>
<div id='fg'> </div>
</body>
css:
body {
margin: 0; padding: 0;
overflow: hidden;
background: url('http://wallpaper.zoda.ru/bd/2006/07/21/2c7b4306fd22f049f331d43adb74a5f7.jpg') no-repeat left top;
}
body, html { width: 100%; height: 100%; }
#fg {
margin: 2%; width: 96%; height: 96%;
opacity: 0.7;
background: url('http://3.bp.blogspot.com/-OYlUbWqyqog/TeL-gXGx3MI/AAAAAAAAHRc/bdqvvvaeC7c/s1600/bald-eagle3.jpg') no-repeat center center;
}
If you know the image dimensions, you could then set max-height and max-width. (I'll try that too :-)
edit again To get the background to crop in a centered way, you'd need to set the position to "center center" instead of "left top". (Or "center top" if you just want it centered horizontally.)
Vertically centering elements with CSS without cutting-edge non-standard features (flexible box layout) is hard. That may be something to do with JavaScript. I'll say that one problem with any JavaScript solution like that is that it really slows the browser down. If you must do it, I would suggest introducing a little time lag so that you don't try to recompute the layout on every resize event. Instead, set a timer for like 200 milliseconds in the future where the work will get done, and each time you do so cancel the previous timer. That way, while a person is dragging the window corner it won't burn up their CPU.
edit even more ooh ooh yes #Kent Brewster's answer with the vertical centering is good - I always forget that trick :-)
There is no way to achieve this effect using only CSS, for two main reasons:
Because you are trying to resize your image, you cannot use the background property and must instead use an <img> tag. Your image will always try to take up as much room as it can if the width and height are not set. Thus, the aspect ratio will not be maintained, or your image will be cropped.
The other caveat of resizing the image is that you will not be able to vertically-align it to the center of your page without knowing its dimensions.