Make a .div act like an image - css

I have a question about the display of a container.
First, I managed to simulate the attribute "object-fit: contain;" for an image by using a verticaly alligned strut and the attribute "text-align: center" (thank you IE).
See it there: http://codepen.io/babybackart/pen/vGQeoK
html:
<body>
<div class="plancheBox">
<div class="strut"></div><!--
--><img src="http://images.forwallpaper.com/files/thumbs/preview/23/236747__kitten-soft-fluffy-tender_p.jpg">
</div>
</body>
css:
body{
height: 100%;
width: 100%;
display: block;
text-align:center;
}
h1, h2{
font-family: Arial, sans serif;
font-weight: 300;
color: white;
}
.plancheBox{
background-color: green;
position: absolute;
display: block;
width: 90%;
height: 90%;
vertical-align: middle;
}
.strut {
height:100%;
display:inline-block;
vertical-align:middle;
}
.plancheBox img{
max-height: 100%;
max-width: 100%;
vertical-align:middle;
}
I wanted to add a text on the image so I put the image and a text-box in a bloc (the text-box is absolute to appear in front of the image).
See it there: http://codepen.io/babybackart/pen/BKGwZL
html:
<body>
<div class="plancheBox">
<div class="strut"></div><!--
--><div class="container">
<img src="http://eskipaper.com/images/photo-cat-1.jpg">
<div class="descriptionBox">
<h1>Joe le chat</h1>
<h2>Post haec Gallus Hierapolim profecturus ut expeditioni specie tenus adesset, Antiochensi plebi suppliciter obsecranti ut inediae dispelleret metum, quae per multas difficilisque causas adfore iam sperabatur.</h2>
</div>
</div>
</div>
</body>
css:
body{
height: 100%;
width: 100%;
display: block;
text-align:center;
}
h1, h2{
font-family: Arial, sans serif;
font-weight: 300;
color: white;
}
.plancheBox{
background-color: green;
position: absolute;
display: block;
width: 90%;
height: 90%;
vertical-align: middle;
}
.strut {
height:100%;
display:inline-block;
vertical-align:middle;
}
.container{
max-height: 100%;
max-width: 100%;
display:inline-block;
vertical-align:middle;
}
.container img{
max-height: 100%;
max-width: 100%;
display:inline-block;
vertical-align:middle;
}
.descriptionBox{
background-color: blue;
position: absolute;
width: 60%;
margin: 0 20% 5% 20%;
bottom: 0;
}
The problem is that my .div ".container" doesn't act like my image in the first example, it overflows on the bottom when the windows' height is small.
Main question: Is there a way to make the ".container" act like the image in the first example ?
Extra-question: How to fix the ratio and the size of the text-box with the size of the image?
Thank you by advance for your answers !

You try to size the container according to it's content and the content according to it's parent at the same time. This does not work. One of it needs to have set some dimensions.
According to your examples it's the image, that should be fit into an container, so I dimension the container and let the image be sized according to it.
CSS:
.container {
height: 100%; /* not max-height */
width: 100%; /* not max-width */
overflow: hidden;
position: relative;
}
.container img {
max-height: 100.1%; /* ".1" just to avoid small lines due to browser rendering */
max-width: 100.1%; /* ".1" just to avoid small lines due to browser rendering */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
The position: absolute is needed to "fit" the image inside your container an position it at the same time. The 50% moves the top-left border of the image to the center of the container, and the transform moves the image by half its width and height back - so it's centered.
Since the above is outdated as per the more information provided by the OP. You'd need additional JS for that:
JS:
$('.plancheBox img').each( function() {
var $img = $(this),
$plancheBox = $img.closest('.plancheBox');
$img.css({
'max-height' : $plancheBox.height(),
'max-width' : $plancheBox.width()
});
$img.closest('.container').css({'position' : 'relative'});
});
CSS:
[...]
.container{
display: table;
margin: 0 auto;
position: absolute;
}
.container img{
max-height: 100%;
max-width: 100%;
width: auto;
height: auto;
}
.descriptionBox{
background-color: blue;
position: absolute;
bottom: 5%;
right: 20%;
left: 20%;
}
[...]
example fiddle: jsfiddle.net/jpu8umd6/2
In case a portrait plancheBox is possible: jsfiddle.net/jpu8umd6/3
When resizing the browser should be considered by JS, add an event handler, that resets the css-changes and calculate the needed values again.
See: jsfiddle.net/jpu8umd6/4
JS:
// calculateImageDimension() contains the JS described above
var resizeEnd;
$(window).on('resize', function() {
clearTimeout(resizeEnd);
resizeEnd = setTimeout(function() {
$(window).trigger('resize-end');
}, 200);
});
$(window).on('resize-end', function() {
$('.plancheBox img').css({
'max-height' : 'none',
'max-width' : 'none'
})
$('.plancheBox .container').css({'position' : ''});
calculateImageDimension();
});

Since .descriptionBox has position: absolute; the (surrounding) .container should probably have position:relative;
https://codepen.io/eye-wonder/pen/EKGPmZ

Related

Why defining body attributes in css?

I have seen some web design lessons that always start with a css like this:
body,html {
display: block;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
I'm trying to figure out what's the point of declaring attributes like width, height or display for body and html that are, if I'm not wrong, by default in browsers.
I thought it would be to prevent and undefined return or similar when accessing the css with js, but the result is the same when the attributes are defined in the css than when left to default:
console.log($("BODY").css('width')); // Always returns the width of the body
I also thought it could be to start the inheritance in cascade elements, but a div inside the body inherits the value just the same.
Anybody knows a solid reason for this approach? any browser / device issue I have missed? future compatibility? plain pedantry?
I'm kind of curious about it.
I found a good reason to define the html and body width and height to 100%. Say you want to vertically align a relative positioned div, you need to put it into an absolute positioned container:
html,
body {
margin: 0;
padding: 0;
}
#container {
position: absolute;
width: 100%;
height: 100%;
}
#main {
background: lightgrey;
position: relative;
top: 50%;
transform: translateY(-50%);
width: 100px;
height: 100px;
text-align: center;
margin-left: auto;
margin-right: auto;
}
<div id="container">
<div id="main">
<h1>MY DIV</h1>
</div>
</div>
But, setting the body width and height to 100% you get an absolute positioned container that covers the whole window:
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#main {
background: lightgrey;
position: relative;
top: 50%;
transform: translateY(-50%);
width: 100px;
height: 100px;
text-align: center;
margin-left: auto;
margin-right: auto;
}
<div id="main">
<h1>MY DIV</h1>
</div>
You get the same result, but it saves you a div element.

How to position a component in the bottom center of a div without knowing its size in Css

which is the style to apply on a div to make component (button) centered in the botton without knowing the size of the remaining space that will take the div and the size of the button because this style will be generic.
I used this style but it didn't work for me:
<div location="buttonLayout" style="display:flex; justify-content:center; align-items:flex-end ;"></div>
The button is centered but not placed in the bottom of the remainig space of the parent div.
You could use absolute positioning to get button at the bottom middle:
.parent {
background: gold;
position: relative;
width: 300px;
height: 400px;
box-sizing: border-box;
padding-bottom: 48px; // Padding + button height
}
.parent button {
background: grey;
border: none;
height: 32px;
color: #fff;
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
}
<div class="parent">
<button>Button any size</button>
</div>
Just add bottom: 0; to the button.
If you have the following HTML:
<div id="flexItem" location="buttonLayout">
<button id="bottomButton" type="button">Click Me!</button>
</div>
You can use this CSS:
html, body{
height: 100%;
width: 100%;
}
body{
margin: 0;
}
#flexItem{
height: 100%;
width: 100%;
display: flex;
justify-content:center;
align-items:flex-end ;
}
#bottomButton{
bottom: 0;
}
JSFiddle.
Remember not to put inline CSS.
try this
.mybutton {
position: absolute;
bottom: 0px;
margin-left: auto;
margin-right: auto;
}
For this to work the parent container also has to have a position setting other than the default (static), for example position: relative;

Scale element to proportionally fill space

The example below has an gray div (#outer) with a child orange div (#inner). #inner will fill the page proportionally on width only. Is it possible to have #inner scale proportionally based on width and height using only CSS? Please, no Javascript solutions as I am aware of how to accomplish it that route, but would prefer a CSS solution if possible.
http://jsfiddle.net/Gchr4/
CSS
body, html {
margin: 0;
padding: 0;
height: 100%;
}
#outer {
background-color: #EFEFEF;
width: 100%;
height: 100%;
}
#inner {
background-color: #ff9933;
width: 100%;
padding-top: 50%;
}
HTML
<div id="outer">
<div id="inner"></div>
</div>
Javascript example of what I am attempting to achieve: http://jsfiddle.net/Q4Qdy/
Use height:100% for the #inner.
However, due to your padding, the height will add 50% to it. This will be fixed by using box-sizing:border-box, but this still has some browser issues. So if you don't have to add padding, i would suggest to remove it.
working example
#inner {
background-color: #ff9933;
width: 100%; height: 100%;
padding-top: 50%;
box-sizing: border-box;
}
It is possible using media queries (and min-aspect-ratio, in particular) and viewport units: http://jsfiddle.net/79Fhb/.
HTML:
<div id="outer">
<div id="inner"></div>
</div>
CSS:
body, html {
margin: 0;
padding: 0;
height: 100%;
}
#outer {
background-color: #bbb;
height: 100%;
}
#inner {
background-color: #ff9933;
}
#inner:before {
content: "";
display: block;
padding-top: 50%;
}
#media screen and (min-aspect-ratio: 2/1) {
#inner {
height: 100%;
width: 200vmin;
}
}

How to center a span containing an image in a div

I have a main div (#homeGallery), in which i have a span(.imgClass) that is used to load one of a list of images.
I need the image to be centered not only vertically but horizontally in the div.
So far I have this code.
#homeGallery > .imgClass{
margin:auto;
position: relative;
top: 0;
bottom: 0;
display: block;
left: 0;
right: 0;
}
and
#homeGallery > .imgClass > img {
margin:auto;
float:center;
max-width:60%;
max-height:99%;
border: 2px solid;
}
Any help would be appreciated
This is a jewel I found recently. Use position: absolute with a top, left, bottom and right. You can center your span horizontally and vertically.
HTML:
<div class="wrapper">
<span class="image"></span>
</div>
CSS:
.wrapper {
width:400px;
height: 400px;
position: relative;
background-color: #afafaf;
}
.wrapper .image {
position: absolute;
top: 25%;
left: 25%;
right: 25%;
bottom: 25%;
background-color: #000;
}
http://jsfiddle.net/QTDrm/
You can try this code:-
#homeGallery > .imgClass > img {
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;
max-width:100%;
max-height:100%;
overflow:auto;
}
You can try the following:
#homeGallery > .imgClass > img {
margin:0px auto;
display:block;
max-width:60%;
max-height:99%;
border: 2px solid;
}
Here's a Fiddle
#homeGallery .imgClass {
position: relative;
width: 200px;
height: 200px;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
}
If you dont know the image width & height than you could use jQuery solution
$(function() {
var imgW = $('.imgClass').outerWidth(),
imgH = $('.imgClass').outerHeight();
$('.imgClass').css({ marginLeft: - imgW / 2 + 'px', marginTop: - imgH / 2 + 'px' });
});
and this CSS
#homeGallery .imgClass {
position: relative;
top: 50%;
left: 50%;
}
This is my prefered method:
HTML
<div id="homeGallery">
<span class="imgClass">
<span class="fakeImg">You can use whatever img you want here</span>
</span>
</div>
CSS
#homeGallery{
height: 400px;
border: 1px solid #333;
text-align: center;
}
#homeGallery:before{
content: '';
height: 100%;
vertical-align: middle;
display: inline-block;
}
.imgClass{
display: inline-block;
vertical-align: middle;
text-align: left;
background-color: blue;
}
jsfiddle here.
The good side is that this is 100% css-based vertical alignment. You don't have to worry about screen size or DOM size change.
The cons is that it doesn't work on IE7 or lower.
If you want to both vertically and horizontally center an element, you should have a look at this approach:
jsFiddle
It works in all current browsers and IE8+.
HTML
<div>
<span class="element"></span> <!-- This can be any element -->
</div>
CSS
html, body {
width: 100%;
height: 100%;
display: table;
}
body > div {
display: table-cell;
vertical-align: middle;
}
body > div > .element {
display: block;
margin: 0px auto;
}
In your specific case with an img inside a span inside a div, I would solve it this way using the approach I have outlined above: jsFiddle
Note that I had to change some CSS classes to get it to work nicely with the image inside the span. I have set text-align: center on the div and display: inline-block; on the span. Below I have inserted the full classes which I have had to change to make it work for your situation.
CSS
body > div {
display: table-cell;
vertical-align: middle;
text-align: center;
}
body > div > .element {
display: inline-block;
}

Position 2 blocks side by side filling the view port with one block set to width:Auto

Lots of discussion here on this topic, but still can't get what I want. I have 2 div blocks that I want to put side by side.
The left most side contains a tree menu and a background color. I have the width set to auto and want the background color to fill the view port vertically regardless of how many nodes are in the tree menu.
I want the contents of the right block to be next to the left block with a 2px margin and have an auto Height and Width that fills the remaing space and gets scroll bars for any overflow.
The only way I have found to get the left block to fill the view port vertically is setting postion:absolute and top: 0px, bottom: 0px. But when I do that I cannot figure out how to position the right block such that it fills the remaining space as the left box expands and contracts in width as the tree expands and collapses.
Is there a way to set the width of the right box based on the current width of the left box?
Basically I have 2 Divs with the following css for those divs...
.treeMenu {
position: absolute;
top: 0px;
bottom: 0px;
width: auto;
margin-right:2px;
padding: 10px;
background: rgba(218, 235, 245, 6);
}
.viewer {
position: relative;
float:right;
width: 100%;
//100% fills the view port width which is not what I want
//a fixed width is not what I want either as it will not adjust to the size of the tree menu.
//if I could set the width or left margin based on the position of the left block's right side I think I could get it to work.
height: 100%;
border: solid;
}
*Thanks to Wesley for the solution to my question*
Working code...
HTML:
<div class="wrapper">
<div class="treeMenu" >
</div>
<div class="viewer">
</div>
</div>
CSS:
body {
width: 100%;
margin: 0 auto;
font: 100% Arial, Arial, Helvetica, sans-serif;
}
.wrapper {
position: absolute;
width: 100%;
height: 100%;
}
.treeMenu {
position: absolute;
top: 0px;
bottom: 0px;
width: auto;
margin-right:20px;
padding: 10px;
background: rgba(218, 235, 245, 6);
}
.viewer {
position: relative;
float:right;
height: 100%;
border: solid;
overflow-x:scroll;
overflow-y:scroll;
}
jQuery:
$(document).ready(function() {
$("div.viewer").append("<img id='theImg' src='Images/FM-000-T01 TITLE INDEX QMC 1824 (1).jpg'/>");
$('div.viewer').width(($(document).width() - $('div.treeMenu').width())-28);
});
$(window).resize(function() {
$('div.viewer').width(($(document).width() - $('div.treeMenu').width())-28);
}).resize();
pureCSS cross-browser solution: (demo on dabblet.com)
html:
<div id="wrap">
<div id="treeMenu">
<div class="content">menu abc</div>
</div>
<div id="viewer">
<div class="content">menu abc</div>
</div>
</div>
css:
#wrap {
position: absolute;
top: 0;
height: 100%;
left: 0;
width: 100%;
}
#treeMenu, #viewer {
height: 100%;
}
#treeMenu {
float: left;
background: rgba(218, 235, 245);
padding-right: 3px;
}
#viewer {
background: red;
overflow-y: auto;
}
I can't think of a way to do with you want with just CSS. Maybe it's possible but I doubt there is a clean solution which works cross-browser.
With a little bit of javascript however, it shouldn't be hard.
It's a bit hard to understand what you want exactly, try following code (jsFiddle here):
html:
<div id="treeMenu">menu abc</div>
<div id="viewer">this is the viewer</div>
javascript (using jQuery because it's easy):
$(document).ready(function() {
$(window).resize(function() {
$('#viewer').width($(document).width() - $('#treeMenu').width());
}).resize();
});
css:
html,body {
height: 100%;
}
#treeMenu {
display: inline-block;
background: rgba(218, 235, 245, 6);
height: 100%;
}
#viewer {
display: inline-block;
position: absolute;
display: inline-block;
background-color: red;
height: 100%;
}

Resources