Scaling div like an image - html

I'm doing a list of items, but it has some challenges:
Responsive;
The "title" may have more than one line;
Sometimes a I need to show a icon with a color in the background instead of full image.
This is the image of what I'd expect:
And what I've got: http://codepen.io/caio/pen/ygkfm/
As you can see, I can't set the same scaling to an "image" div when it has a icon. Is there any solution for my problem?

I am assuming your images (exept icons) all have the same aspect ratio as in your example.
In this case, you can use padding bottom to keep the height of the image container. As padding-bottom is calculated according to the width of the container, it will keep it's aspect ratio whatever the content (you will have to position the content with position:absolute; so it doesn't change the dimesions of the container).
Here is a demo Showing what you can do.sorry I'm not into codePen
I also added an other container to center the icons horizontaly.
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.items {
margin: 50px auto 0;
width: 90%;
*zoom: 1;
}
.items:before, .items:after {
content:" ";
display: table;
}
.items:after {
clear: both;
}
.items .item {
border: 1px solid #ddd;
float: left;
width: 32%;
}
.items .item:nth-child(3n+2) {
margin: 0 2%;
}
.items .item .image {
background: #eee;
padding-bottom:50%;
position:relative;
}
.items .item .image .img_in{
position:absolute;
width:100%;
height:100%;
text-align:center;
}
.items .item .image img {
display: block;
width: 100%;
height:100%;
}
.items .item .image img.icon {
height: 80%;
margin:0 auto;
position: relative;
top: 10%;
width: auto;
}
.items .item .title {
margin: 0;
padding: 20px;
}

It's easy
add follwing to .items .item .image
when you have a 'normal' width and height of 200 and 100 Pixels, then 50% represents the 50% of the width (200 * 50% = 100)
{
height: 0;
padding-bottom: 50%;
}
http://codepen.io/HerrSerker/pen/HhjKo?editors=110
edit
You can use SCSS percentage function:
padding-bottom: percentage(100px / 200px);

This is not exactly what you had in mind however it is a very responsive design which I expect to be what you need: http://codepen.io/anon/pen/DwudI
Here's the gist: You probably want to keep the aspect ratio of each main container. The image then scales to at least 80% of the height and no more than 100% in both width and height. The way to create an aspect ratio on a div is by using this fun padding-top trick. When you resize the screen the div's width changes which causes the height to change to (aspect ratio). So if you resize smaller then eventually the div becomes smaller than the image size which will cause the 200x100 to fill the entire div.
So if you want the image to fill the div, then it must be (A) larger than the div and (B) the same aspect ratio as the div.
You mentioned the title might be multiple lines: Right now new lines go below. If you wanted the text to 'float upwards' then that wouldn't be too hard. Simply use position:absolute; bottom:0px on the header and make sure .item has position:relative.

I think you are going about this the wrong way, when everything is based on the width percentages there is no way to know the height unless you use JS, so you need to change the width to something more appropriate to achieve your goal.
changing your CSS to:
.icon {
margin: 0 auto;
padding: 5% 0;
width: 40%;
}
and it will look more like you want. I updated your CodePen

Mainly, I added a max-height and a min-height of the same value to .items .item .image img:
.items .item .image img {
display: block;
width: 100%;
max-height:23%;
min-height:23%;
}
I'm not quite sure what you're trying to achieve but if I got you well then this is what you're looking for, Here is the full code:
HTML
<div class="items">
<a href="#" class="item">
<div class="image">
<img src="http://placehold.it/200x100" />
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
<a href="#" class="item">
<div class="image">
<img src="http://placehold.it/80x80" class="icon" />
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
<a href="#" class="item">
<div class="image">
<img src="http://placehold.it/200x100" />
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
</div>
CSS
* {
#include box-sizing(border-box);
}
.items {
margin: 50px auto 0;
width: 90%;
#include clearfix;
}
.item {
border: 1px solid #ddd;
float: left;
width: 30%;
}
.items .item .image {
background: #eee;
}
.items .item .image img {
display: block;
width: 100%;
max-height:23%;
min-height:23%;
}
.items .item .title {
margin: 0;
padding: 20px;
}
.icon {
height: 80%;
margin: 0 auto;
position: relative;
top: 10%;
width: auto;
}
.items .item:nth-child(3n+2) {
margin: 0 2%;
}
And here is a FIDDLE

I thing this is what you are excepting.
Demo
HTML
<a href="#" class="item">
<div class="image">
<div><img src="http://placehold.it/200x100"></div>
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
<a href="#" class="item">
<div class="image">
<div><img src="http://placehold.it/80x80" class="icon"></div>
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
<a href="#" class="item">
<div class="image">
<div><img src="http://placehold.it/200x100"></div>
</div>
<h4 class="title">Hi. I'm a title.</h4>
</a>
</div>
SCSS
* { #include box-sizing(border-box); }
.items {
margin: 50px auto 0;
width: 90%;
#include clearfix;
.item {
border: 1px solid #ddd;
float: left;
width: 32%;
&:nth-child(3n+2) { margin: 0 2%; }
.image {
background: #eee;
min-height:100px;
max-height:100px;
display:table;
width:100%;
&> div {
display:table-cell;
text-align:center;
vertical-align:middle;
}
img {
max-width:100%;
height:100%;
margin:0 auto;
&.icon {
height: 80%;
margin: 0 auto;
position: relative;
top: 10%;
width: auto;
}
}
}
.title {
margin: 0;
padding: 20px;
}
}
}

I'd rather go and use those utility classes which I found myself using quite a lot since I found them, basically embedding them on each CSS I write. Clean, easy to read and easy to embed in the HTML.
This small set of classes permits you to have a proportional width/height sizes on elements.
Here's the demo http://siebennull.com/equal_width_height.html
Here's the article explaining it: http://www.mademyday.de/css-height-equals-width-with-pure-css.html
Credit obviously goes to who found this trick :)
CSS
.box{
position: relative;
width: 50%; /* desired width */
}
.box:before{
content: "";
display: block;
padding-top: 100%; /* initial ratio of 1:1*/
}
.content{
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
/* Other ratios */
.ratio2_1:before{
padding-top: 50%;
}
.ratio1_2:before{
padding-top: 200%;
}
.ratio4_3:before{
padding-top: 75%;
}
.ratio16_9:before{
padding-top: 56.25%;
}
HTML
<div class='box'>
<div class='content'>Aspect ratio of 1:1</div>
</div>
<div class='box ratio16_9'>
<div class='content'>Aspect ratio of 16:9</div>
</div>

You could use an extra element and vertical-padding to force your div to keep the same ratio that it has a 2:1 image or not.
DEMO and basic css:
.image:before {
content:'';
display:inline-block;
vertical-align:middle;
padding-top:50%;/* equals 50% of width of parent */
width:0;
box-shadow:0 0 0 5px red;/* let's see where it stands for demo purpose */
}
In order to have this working in your codepen:
img should turn back to their default display (inline-block), so just remove display:block; and be vertical-alligned in middle to the pseudo element , the gap under img that appears when on baseline, will be no longer here.
.image needs either:
In CSS font-size:0;
In HTML, the code <div><img src=".. should not be indented
In HTML white-space should be commented <div><!-- code indented --><img src="...
to avoid extra white-space and break in 2 lines when img is full width.
I did link in the demo another version where image could be bigger than initial space wanted without breaking the layout (base on idea that elements remain in the flow, no absolute positionning involved): EXTRA

Maybe you could try this jQuery library http://brm.io/jquery-match-height/
To use it you assign data attributes to the elements whose heights you want to match, it then calculated the height of each element to make are they are all the same. It takes in to account padding, margin, border and box-sizing.

Related

Responsive img css with a twist

I'm trying to get an image (img) to fill all available space inside a div BUT also I want the img itself to be inside an equaly sized container with position:relative so that I can place markers on the image with absolute position.
I have tried using div background-image and that works perfect except that my markers positions are out of place (of course) since the parent div is not the same size.
And with I get the markers to work perfect but then the image doesn't scale with parent container.
I need the image to behave like background-image but I also need the parent container to be same size.
Here I have 2 pens showing what I mean.
First one with background-image. pen:background-image
body { height: 90vh;
background: aliceblue;}
.page-inner {
aspect-ratio: 16 / 9;
position: relative;
padding: 1em 1em 0 1em;
display: flex;
flex-direction: column;
align-items: center;
height:100%;
border: 1px solid black
}
.main-container {
width: 100%;
flex: 1;
padding: 2em 1em 2em 1em;
background:yellow;
}
.working-area {
position:relative;
}
.work-item {
position:absolute;
top:10%;
left:10%;
background:white;
outline: 2px solid black;
}
<div class="page-inner">
<h3 class="" >Some text</h3>
<div class="main-container">
<div class="working-area" style="height:100%;width:100%;background-position: center;background-image:url('');background-size: contain;background-repeat: no-repeat">
<div class="work-item">X</div>
</div>
</div>
<div>
<h3 class="" >Some text again</h3>
</div>
</div>
Second one with img: pen:img
body { height: 90vh;
background: aliceblue;}
.page-inner {
aspect-ratio: 16 / 9;
position: relative;
padding: 1em 1em 0 1em;
display: flex;
flex-direction: column;
align-items: center;
height:100%;
border: 1px solid black
}
.main-container {
width: 100%;
flex: 1;
padding: 2em 1em 2em 1em;
background:yellow;
}
.main-container img {
width: 100%;
height: auto;
}
.working-area {
position:relative;
}
.work-item {
position:absolute;
top:10%;
left:10%;
background:white;
outline: 2px solid black;
}
<div class="page-inner">
<h3 class="" >Some text</h3>
<div class="main-container">
<div class="working-area">
<img src="" style="" />
<div class="work-item">X</div>
</div>
</div>
<div>
<h3 class="" >Some text again</h3>
</div>
</div>
I want to combine these 2 into one :-) I need full scaling of image at the same time as I need to get image size and position relative so I can place my markers.
The image can be in any size and the screen can be resized at any time, so I need a solution that really is responsive.
thanks!
I have tried width:100%;height:auto; nad like 200 other different things. I have also started to calculate the image aspect-ratio and have a hidden img and then manually, with js, calculate each marker pos in % based on parent div size.
The solution needs to work with all img sizes and aspect ratios. Users uploads image so I don't know what sizes will come.
I have also tried to position the image with full width and height and then used transform: scale to make it fit the parent div with lots of calculations in js.
But there has to be an easier way :-)

Set the margin or padding between two images next to eachother

I am trying to set the margin or padding between two image which are next to eachother, somehow the margin seems to be also 40%, namely the width of one image. How to set my own margin/padding between the images of lets say 2px???
.certifications, .car {
display:inline-block;
position:relative;
vertical-align:middle;
}
.certifications img {
max-width: 40%;
height: auto;
}
.car img {
max-width: 40%;
height: auto;
}
#wrapper.car {
max-width: 100%;
height:auto;
}
<div id="wrapper car">
<div class="car"><img alt=
"" src="http://lorempixel.com/100/100"></div>
<div class="certifications"><img alt=
"" src="http://lorempixel.com/100/100""></div>
</div>
It sounds like you want each image to be 40% of the wrapper's width. Right now each image is 40% of the #wrapper > div's width. I
removed unnecessary styles from #wrapper
made .certifications and .car 40% of the #wrapper's width, given them spacing on the right, and made the images full width
made .certifications and .car blocks, because whitespace in your html between inline-blocks will actually take up space in the rendered page
changed max-widths to widths
.certifications,
.car {
display: block;
float: left;
position: relative;
vertical-align: middle;
width: 40%;
padding-right: 20px;/* could also use margin */
}
img {
width: 100%;
height: auto;
}
<div id="wrapper">
<div class="car">
<img alt="" src="http://lorempixel.com/100/100">
</div>
<div class="certifications">
<img alt="" src="http://lorempixel.com/100/100">
</div>
</div>
Change the inline-block to inline. Then you can add a margin for spacing:
.certifications, .car {
display:inline;
margin-right: 10px;
position:relative;
vertical-align:middle;
}
.certifications img {
max-width: 40%;
height: auto;
}
.car img {
max-width: 40%;
height: auto;
}
#wrapper.car {
max-width: 100%;
height:auto;
}
<div id="wrapper car">
<div class="car"><img alt=
"" src="http://lorempixel.com/100/100"></div>
<div class="certifications"><img alt=
"" src="http://lorempixel.com/100/100""></div>
</div>

Child divs wont fit to parent

I'm working on my portfolio site and having trouble getting my divs to size together.
Here it is: I have one body div, inside there are two child divs.
The body div should have max-height 100%, max-width: 100% so that it doesn't exceed the browser window.
The left div contains an image which I want to scale to the parent body div (max-height 100%, max-width 70%).
The right div contains text about the image, it needs to scale to the height of the left div (there is also footer that sits at the bottom of this div).
This shouldn't be so hard, its almost working but right now my image container (left div) is not being contained to the body div.
html,
body {
height: 100%;
}
.Info {
float: left;
width: 25%;
padding-left: 15px;
padding-top: 10px;
/*margin-left: 78%;*/
border-left: 1px black solid;
/*position: absolute;*/
}
.InfoText p {
margin-top: -10px;
}
div img {
max-width: 100%;
max-height: 100%;
margin: 0 auto;
box-shadow: 5px 5px 15px #888888;
}
.ImageContainer {
float: left;
height: 100%;
max-width: 70%;
padding-right: 15px;
position: relative
}
section.ImageContainer img {
float: left;
object-fit: cover;
}
#SideQuote {
margin-top: 30px;
}
.StuffInBody {
position: relative;
padding-top: 15px;
float: left;
display: flex;
}
footer p {
position: absolute;
bottom: 0%;
margin: 0;
}
<div class="StuffInBody">
<div class="ImageContainer">
<img class="contained" src="images/TheGMODebate copy.jpg" alt="" />
</div>
<div class="Info">
<div class="InfoText">
<p>ILLUSTRATION</p>
<p>Title: <em>The GMO Debate</em>
</p>
<p>Media: Gouache</p>
<div id="SideQuote">
<p class="ClickToEnlarge">Full screen image click here.
</p>
</div>
<footer>
<p>© Brooke Weiland 2015</p>
</footer>
</div>
</div>
</div>
It's very hard to make a reliable interface using floats.
It changes default behaviour and put your element outside of the flux.
You should be able to do what you want using only flex.
The property box-sizing: border-box also makes miracles (margin and padding easier to manage).
Also, the object-fit property is not enough supported by browsers to be used now IMHO.
http://caniuse.com/#feat=object-fit

How to position a div with equal margins for left, right, and top

I would like to achieve a layout that looks like this:
I am interested in a css/html only solution, so no javascript required.
The widths of both divs are dynamic, so I cannot use any static margins.
The spacing between the sides of the divs, and the top, should be the same.
I tried using margin: auto auto 0 auto on the inner div, as you can see in this jsfiddle, but it only works for left and right.
Note, the following attempt doesn't answer the question fully, since the width of the child cannot be dynamic.
The idea is to use a percentage width + percentage margin-top values on the child. It's a responsive layout, see the comments in the code, and try it out on different window sizes.
JSFiddle: http://jsfiddle.net/jkoycs6e/
body {
margin: 0;
}
.outer {
height: 100vh; /*for demo only*/
background: teal;
overflow: auto;
}
.inner {
width: 80%;
background: gold;
margin: auto;
margin-top: 10%; /* 100%-80%/2 */
}
<div class="outer">
<div class="inner">
hello<br/>hello<br/>hello
</div>
</div>
This is not possible. At least not without using javascript. There is no css-only solution.
If you put align="center" in your div you'll get to the middle of the screen every time but it's not going to be supported in HTML5 so I recommend the 50:50 approach.
div
{
text-align:center;
margin-top:50%;
margin-bottom:50%;
}
Hope that helps. ^^
Set the outer parent's overflow to auto and give your margin-top a relative value. Something like this:
.outer {
background: blue;
overflow: auto;
}
.inner {
background:yellow;
width: 100px;
height: 100px;
margin: 1em auto 0 auto;
}
<div class="outer">
<div class="inner">
</div>
</div>
This seems to work:
.outer {
height: 500px;
width: 300px;
background: blue;
position: relative;
}
.inner {
width: 80%;
height: 200px;
background:green;
position: absolute;
margin-left: 10%;
margin-right: 10%;
margin-top: 10%;
margin-bottom: 0;
}
You can change the percentages marked for the margins as per your intended value for k.
Here's the fiddle
EDIT: Note that the width of inner has to be set in terms of percentages for this to work. Also note that when a margin is specified in terms of percentage, the margin's value is computed as a percentage of the width of the container. Even for the vertical margins, the percentage is applied on the width (and NOT the height) of the container.
Here's an SO post that's helpful in understanding how to position elements with respect to their container.
This answer doesn't actually make use of the margin property, nor does it have only two div.
body {
font-size: 26px;
text-align: center;
font-family: monospace;
}
#container {
display: inline-block;
position: relative;
width: 100%;
}
#dummy {
margin-top: 20%;
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver
/* show me! */
}
#wrapper {
display: table;
width: 100%;
}
#row {
display: table-header-group;
}
#left {
display: table-cell;
background-color: chartreuse;
width: 20%;
}
#incenter {
display: table-cell;
background-color: aqua;
}
#right {
display: table-cell;
background-color: chartreuse;
width: 20%;
}
<div>
<div id="container">
<div id="dummy"></div>
<div id="element">
k (20%)
</div>
</div>
<div id="wrapper">
<div id="row">
<div id="left">width = k (20%)</div>
<div id="incenter">incenter</div>
<div id="right">width = k (20%)</div>
</div>
</div>
</div>
Another example with measurements in pixels is here.
For explanation refer:
https://stackoverflow.com/a/12121309/2534513
https://stackoverflow.com/a/6615994/2534513
I have actually combined techniques mentioned in above two answers to make this one.
Using JavaScript would have been a lot easier.

center image in div with overflow hidden

I have an image of 400px and a div that is smaller (the width is not always 300px as in my example). I want to center the image in the div, and if there is an overflow, hide it.
Note: I must keep the position:absolute on the image. I'm working with css-transitions, and if I use position:relative, my image shakes a bit (https://web.archive.org/web/20120528225923/http://ta6.maxplus.be:8888/).
jsfiddle
http://jsfiddle.net/wjw83/1/
You should make the container relative and give it a height as well and you're done.
http://jsfiddle.net/jaap/wjw83/4/
.main {
width: 300px;
margin: 0 auto;
overflow: hidden;
position: relative;
height: 200px;
}
img.absolute {
left: 50%;
margin-left: -200px;
position: absolute;
}
<div class="main">
<img class="absolute" src="http://via.placeholder.com/400x200/A44/EED?text=Hello" alt="" />
</div>
<br />
<img src="http://via.placeholder.com/400x200/A44/EED?text=Hello" alt="" />
If you want to you can also center the image vertically by adding a negative margin and top position: http://jsfiddle.net/jaap/wjw83/5/
None of the above solutions were working out well for me. I needed a dynamic image size to fit in a circular parent container with overflow:hidden
.circle-container {
width:100px;
height:100px;
text-align:center;
border-radius:50%;
overflow:hidden;
}
.circle-img img {
min-width:100px;
max-width:none;
height:100px;
margin:0 -100%;
}
Working example here:
http://codepen.io/simgooder/pen/yNmXer
Most recent solution:
HTML
<div class="parent">
<img src="image.jpg" height="600" width="600"/>
</div>
CSS
.parent {
width: 200px;
height: 200px;
overflow: hidden;
/* Magic */
display: flex;
align-items: center; /* vertical */
justify-content: center; /* horizontal */
}
Found this nice solution by MELISSA PENTA (https://www.localwisdom.com/)
HTML
<div class="wrapper">
<img src="image.jpg" />
</div>
CSS
div.wrapper {
height:200px;
line-height:200px;
overflow:hidden;
text-align:center;
width:200px;
}
div.wrapper img {
margin:-100%;
}
Center any size image in div
Used with rounded wrapper and different sized images.
CSS
.item-image {
border: 5px solid #ccc;
border-radius: 100%;
margin: 0 auto;
height: 200px;
width: 200px;
overflow: hidden;
text-align: center;
}
.item-image img {
height: 200px;
margin: -100%;
max-width: none;
width: auto;
}
Working example here codepen
For me flex-box worked perfect to center the image.
this is my html-code:
<div class="img-wrapper">
<img src="..." >
</div>
and this i used for css:
I wanted the Image same wide as the wrapper-element, but if the height is greater than the height of the wrapper-element it should be "cropped"/not displayed.
.img-wrapper{
width: 100%;
height: 50%;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
img {
height: auto;
width: 100%;
}
working solution with flex-box for posterity:
main points:
overflow hidden for wrapper
image height and width must be specified, cannot be percentage.
use any method you want to center the image.
wrapper {
width: 80;
height: 80;
overflow: hidden;
align-items: center;
justify-content: center;
}
image {
width: min-content;
height: min-content;
}
<html>
<head>
<style type="text/css">
.div-main{
height:200px;
width:200px;
overflow: hidden;
background:url(img.jpg) no-repeat center center
}
</style>
</head>
<body>
<div class="div-main">
</div>
</body>
just make sure how you are using image through css background use backgroud image position like background: url(your image path) no-repeat center center; automatically it wil align center to the screen.
this seems to work on our site, using your ideas and a little math based upon the left edge of wrapper div. It seems redundant to go left 50% then take out 50% extra margin, but it seems to work.
div.ImgWrapper {
width: 160px;
height: 160px
overflow: hidden;
text-align: center;
}
img.CropCenter {
left: 50%;
margin-left: -100%;
position: relative;
width: auto !important;
height: 160px !important;
}
<div class="ImgWrapper">
<img class="CropCenter" src="img.png">
</div>
I have been trying to implement Jaap's answer inside this page of my recent site, with one difference : the .main {height:} was set to auto instead of a fixed px value.
As responsive developer i am looking for a solution to synchronize the image height with the left floating text element, yet only in case my text height becomes greater then my actual image height.
In that case the image should not be rescaled, but cropped and centered as decribed in the original question here above.
Can this be done ?
You can simulate the behaviour by slowly downsizing the browser's width.
This issue is a huge pain in the a.. but I finally got it.
I've seen a lot of complicated solutions. This is so simple now that I see it.
.parent {
width:70px;
height:70px;
}
.child {
height:100%;
width:10000px; /* Or some other impossibly large number */
margin-left: -4965px; /* -1*((child width-parent width)/2) */
}
.child img {
display:block; /* won't work without this */
height:100%;
margin:0 auto;
}
you the have to corp your image from sides to hide it try this
3 Easy and Fast CSS Techniques for Faux Image Cropping | Css ...
one of the demo for the first way on the site above
try demo
i will do some reading on it too