I would like to center and clamp the dimensions of a child div inside its parent.
<style type='text/css'>
.parent {
width: 100%;
height: 100%;
}
.child {
max-width: 100%;
max-height: 100%;
}
</style>
<div class="parent">
<div class="child">
<img src='dog.jpg' />
</div>
</div>
Here are the constraints:
The parent div is set to occupy the entire screen (of unknown size), so width:100% and height:100%.
The width and height of the child div are unknown. In one use case, the child div contains an image. In another, it contains a video.
The width and height of the child div must be constrained to the size of the parent, so max-width: 100% and max-height: 100%.
The child div must be vertically and horizontally centered inside the parent.
Ideally, this should work without javascript.
IE can be left unsupported :)
I've tried all the techniques listed in this excellent article, 'Absolute Centering in CSS' , and none of them pan out. Here's why:
Absolute centering: In order for this technique to work with a child of unknown size, you must set display:table on the child. You can then constrain the max-width of the child's contents, but not the max-height, because by CSS 2.1 rules, tables render to fit their contents.
Negative margins: Doesn't allow for variable height.
Transforms: Undesirable because it can result in blurry rendering.
Table-cell: Fails for the same reason that absolute centering fails, i.e. table rendering.
Inline-block: Doesn't work in the important case where the child is 100% width.
Flexbox: Works well until a window resize occurs, at which point you have to force a Webkit redraw to propagate the centering changes. This hack does the job, but it's still a hack. I want to believe there's a more elegant solution to this.
Best solution here is to use :before pseudo element. Check out this article on centering the unknown, http://css-tricks.com/centering-in-the-unknown/
SEE THE DEMO HERE
body,html {
width: 100%;
height: 100%;
margin: 0;
}
.container {
text-align: center;
background: #ccc;
width: 100%;
height: 100%;
}
.container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
.image {
display: inline-block;
max-width: 100%;
max-height: 100%;
vertical-align: middle;
padding: 10px 15px;
border: #a0a0a0 solid 1px;
background: #f5f5f5;
}
You could use display:table and display:table-cell like so Jsfiddle. Though this will just center the image of the child div.
If you need to have a centered div around the image you could always add another div inside of the child div with the style display: inline-block example
Related
Im trying to wrap a div around a image both when the width or height changes.
The issue is that when the width changes the div does not tightly wrap against the child in this case the child is a image:
Wrap div around a image current result
I did determine that setting the flex-direction between row and column solves it when the div gets resized and could use something like a resize observer to toggle the flex direction but hope there is a css solution to this?
Here is a code pen with the issue: https://codepen.io/quinnaz/pen/rNJdjJy
<div class="container direction-row">
<div class="border">
<img src="https://dummyimage.com/400x600/d4b9d4/7477a3.png" class="img-element" />
</div>
</div>
.container {
resize: both;
overflow: auto;
background-color: beige;
border: solid;
display: flex;
}
.direction-row {
flex-direction: row;
}
.direction-col {
flex-direction: column;
}
.img-element {
max-width: 100%;
max-height: 100%;
display: block;
}
.border {
border-width: 50px;
border-color: blue;
border-style: solid;
}
You need to use the object-fit property and give it the value cover. I would also change max-width and max-height to width and height respectively.
The replaced content (in this case an image) is sized to maintain its aspect ratio while filling the element's entire content box. If the object's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit.
codepen link https://codepen.io/thechewy/pen/ZErxevo
.img-element {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
** EDIT **
If you want it to fully fit the .container div you'll then need to make the .border div fill the parent .container with width: 100%; height: 100%; set on .border, this isn't clear in the question though. If not the above snippet should do the trick.
Personally I would just add the border to the image and remove the extra div and CSS.
I like to think I'm pretty good with CSS, but this issue is driving me crazy.
I'm trying to get 3 columns to be 100% height. The first two columns are floated left, the third is not floated, just margined over. There is a wrapper around all 3 columns that clears the floats. The HTML/BODY tag have 100% height on them. As far as I know, if all parent containers have 100% height, it should work. The wrapper should be as tall as the tallest content block (third column), so the first two columns should be that tall too, using 100% height.
Problem is, the wrapper, and thus the body tag, have a height equal to that of the browser window. For some reason it won't read the middle columns content height. There is probably a super stupid simple explanation for this and I'm just missing it.
Don't want an overflow hack. Cannot do faux columns. I don't see why this can't work using the CSS spec for height.
If I put a pixel amount on the wrapper div, like a 2000px height, the first two columns fill the height just like I want them to. Why isn't this working??
HTML:
<body>
<div class="wrapper clearfix">
<section class="sidebar-news clearfix"></section>
<section class="black-bar-vertical"></section>
<section class="section-main-content event-detail"></section>
</div>
</body>
CSS:
html {
height: 100%;
}
body {
background-color: #333;
height: 100%;
* {
box-sizing: border-box;
}
}
.wrapper {
height: 100%;
position: relative;
margin: 0 auto;
}
.sidebar-news {
float: left;
width: 300px;
height: 100%;
min-height: 100%;
background-color: #site-color-yellow;
margin-right: -25px;
padding: 76px 40px 20px 20px;
}
.black-bar-vertical {
position: relative;
float: left;
width: 116px;
background: url("#{img-path}/black-bar-vertical.png") repeat-y top center;
min-height: 100%;
height: 100%;
text-align: center;
margin-right: -25px;
padding-top: 81px;
z-index: 50;
}
.section-main-content {
width: 580px;
background-color: #FFF;
padding-top: 55px;
padding-left: 10px;
margin-left: 360px;
}
SCREENSHOTS:
Top & Bottom of page
The height of the two columns in dev tools
EDIT:
Found this article, which is basically the same problem.
html body is smaller than its contents
If I change the height property to min-height on the body, the wrapper becomes the full height of the content, yay! But then the 100% heights on the first two columns don't work at all.
Like I originally thought... if 100% height is set on an element, it bubbles up the dom, and inherits the height of it's parent container. If that parent container has 100% height, it inherits the height of the parent's parent, etc. That works as expected. But when it hits the body tag, with 100% height, it's reading that as 100% height of the browser window. That's the default behavior, which doesn't make sense to me. If you take off the height on the body, it encompasses all content, but then the wrapper div looks up to the body for it's height definition and get's nothing because there is no height set on the body.
It's seeming like this specific scenario isn't really possible without using flexbox, table layout, javascript, or absolutely positioned elements.
Flexbox fo-sho!
.wrapper {
min-height: 100vh;
width: 100vw;
display: flex;
align-items: stretch;
}
.sidebar-news {
min-height: 100vh;
flex-grow: 1;
}
.black-bar-vertical {
min-height: 100vh;
flex-grow: 1;
}
.section-main-content {
min-height: 100vh;
flex-grow: 1;
}
Check this out for ref- Flexbox CSS Tricks
I've decided to do a combination of faux columns to get the first and third columns background colors, and then an absolute positioned second column that I can stretch full height using top: 0, bottom: 0.
If anyone can still solve this problem, I'd love to hear how it's done!
I have a ul of imgs to create a side-scrolling gallery.
I'd like for the images' height to be constrained to the browser window and their width to resize in order to maintain their scale.
Even though I've specified a height for every containing element, the images with height:90%; are way bigger than the browser window. See the fiddle here: JSFiddle
What am I doing wrong here?
Additional info: If I set height: 90vh; on .gallery-image it looks pretty much exactly how I want it, but it feels like a hack and I'd like to understand why % isn't working.
I'm looking to achieve this functionality: example.
This might be what your looking for?
http://jsfiddle.net/jny0u3rc/11/
I simplified the code, this might not work if you have to have the images loaded in as list-items.
This specifies a container height of 100% and an image height of 90%. images are inline elements by default, so I set them to
white-space:nowrap and overflow:auto on the container.
The CSS:
.gallery {
height: 100%;
overflow: auto;
white-space:
nowrap; }
.gallery img{
margin: 20px 10px 0 0px;
height:90%
}
Is this what you're looking for? http://jsfiddle.net/jny0u3rc/8/
.gallery {
height: 100%;
overflow-x: scroll;
white-space: nowrap;
width: 100%;
}
.gallery-list {
list-style: none;
margin-top: 15px;
margin-bottom: 0px;
height: 100%;
}
.gallery-listitem {
padding-top:0px;
padding-right: 10px;
height: 100%;
display:inline-block
}
.gallery-image {
height:90%;
width:auto;
}
There are two issues:
You forgot to add 100% height on the html and body elements
You are using display: table and display: table-cell. The 100% height technique does not work on table displays. Change this to display: block and display: inline-block and you will get the expected results.
(Heavily) Modified Fiddle
You can achieve what you want by adding a width to each image. Of course the width doesn't have to be static. You can add a width of 100% and then set the height to auto so the images scale.
For a span to take a height, it has to be inline-block.
For an element to serve as offset parent (against which percentage heights of children are computed), it has to have position set. This is quite basic CSS.
See jsfiddle.net/6xh6wbpL/2.
I have two elements, both with display: inline-block, and the parent has white-space: nowrap.
When the screen is resized, the div on the right side don't resize, like this.
I'm trying to make only the blue div resize.
Full source (jsfiddle)
The structure of the html is like this:
<div class="container">
<div class="header">...</div> <!-- red -->
<div class="aside">...</div> <!-- pink -->
<article>...</article> <!-- blue -->
</div>
Relevant css:
* {
box-sizing: border-box;
}
div.container {
margin: 0 auto;
max-width: 40em;
padding: 0;
white-space: nowrap;
}
div.container > * {
white-space: normal;
}
.aside {
display: inline-block;
max-width: 15em;
vertical-align: top;
}
.article {
display: inline-block;
max-width: 25em;
}
Old question, but for the sake of knowledge of anyone who reads this and also has the doubt:
What I've found is that setting position: relative on the .container
and position: absolute on the .article does what I want.
An absolute positioned element is positioned relative to the nearest positioned ancestor, where a positioned element means anything with a position property different to static, the default; if does not found any positioned element, uses the body element.
The absolute positioned elements, if has their width and heigth in auto, resizes to fit its content, and limits the maximun sizes by its positioned ancestor. You can check this putting a short string instead a large one: the element will shrink to the length of text. If you remove the positioning from div.container, the article (if still positioned absolute) will grow (depending on its content) to cover the space between previous element and body width.
And, related to the aforementioned and to add some utility to this delayed answer, a not-very-know bonus: if you define the right and left properties of a absoluted positioned element, and leave the width in auto, the element will cover the horizontal size between the right and left defined. This way you could put something like
article {
background-color: #a0f4ec;
display: inline-block;
position: absolute;
right: 0;
left: 30%;
}
div.aside {
background-color: #faf;
display: inline-block;
max-width: 15em;
width: 30%;
}
This trick also applies in a vertical sense, but with height, top and bottom properties.
There are a few ways to do it.
Method 1:
two divs the same line, one dynamic width, one fixed
Method 2 (negative margins)
http://alistapart.com/article/negativemargins
Unfortunately, Narxx's answers require the divs to be floated. I'm sure that's what you should do if you're building a real site, but in my case, I'm trying not to use it.
What I've found is that setting position: relative on the .container and position: absolute on the .article does what I want.
Simplified fiddle
If anyone can explain why, I'll mark it as an answer.
HTML:
<div class="content">
<div class="card">
</div>
</div>
CSS:
.content {
min-height: 350px;
min-width: 320px;
max-width: 350px;
padding: 15px;
}
.card {
width: 100%;
height: 100%;
background-color: black;
}
http://jsfiddle.net/aJhEF/1/
When examined with console, it shows that .content has functioning width and height. Then why does the child element, with its width and height being set to 100% not fill out its parent's width and height?
Child elements don't inherit their parents min-height property
This is why the .card element has a height of 0
As far as width is concerned, .card does fill out it's parent's width.
Danield is right.
You might solve this by using relative and absolute positions, combined with a negative margin (to compensate the padding):
.content {
min-height: 350px;
min-width: 320px;
max-width: 350px;
padding: 15px;
position: relative;
}
.card {
width: 100%;
height: 100%;
background-color: black;
position: absolute;
margin: -15px;
}
Because you gave the parent a set padding.
Remove padding: 15px; to fill out the div.
padding is extra space at the inside of the elements borders. If you want space around the outside, use margin.
You stated that you wanted your child to fill out the parent element, and since padding it is extra space on the inside of the parent element, the child will not fill out it's parent as long as the padding is there.
Edit: The reason you don't see the results you wanted is because you have your element a min-height and min-width instead of actual sizes. You need to give this element set size (be it pixels or %). This is due to the fact that your child element doesn't inherit the min and max width/height of it's parent.
See JSFiddle