Scrollbar creating empty space in div - html

Fiddle: https://jsfiddle.net/Alexander6RI/vpeasg1t/
I have an image which resizes to fill the height of its parent div, and the parent div has its width set to min-content. This works as expected.
When a horizontal scrollbar is added, the image correctly resizes to keep its aspect ratio while filling the available height. The problem is, the parent div continues to behave as if the image were full size which creates an empty space to the right. The intended function would be for the div to become narrower, because it has width: min-content, but it doesn't.
Is this an intended feature to improve document flow? Is there a way to make it follow the expected behavior?

The width is fine, it works as it should. The problem is the height, the height of the horizontal scroll bar is taken from the height: 50vmin; so the new height of the but the image tries to maintain its aspect ratio so it gets squashed down. Even though the height changes, (because again, the height of the horizontal scroll bar takes up some part of the parent's height.) the viewport doesn't so the height stays constant.
.parent {
outline: 2px solid black;
width: min-content;
resize: vertical;
overflow-y: auto;
}
.child {
outline: 2px solid red;
height: 100%;
width: auto;
display: block;
}
But if you need the height you might need to set the height of the parent and the child to be the same value then set the overflow to hidden like so
.parent {
outline: 2px solid black;
width: min-content;
resize: vertical;
height: 50vmin;
overflow:hidden;
}
.child {
outline: 2px solid red;
height: 50vmin;
width: auto;
display: block;
}
A fraction of the image gets clipped at the bottom but that's the best solution I can think of.

You can probably use the object-fit css property like this:
.parent {
outline: 2px solid black;
width: min-content;
height: 50vmin;
resize: vertical;
overflow-y: auto;
}
.child {
outline: 2px solid red;
height: 100%;
object-fit: cover;
display: block;
}
With cover value you can maintain the aspect ratio using all of image's parent space (the image will be adapted to the new space).

Related

How to cover input field to the rest of the parent div

Please see the attached image below:
div:a is the parent div which width is set to 100%, so no matter the width of the device (pc/mobile) is, it should grow to the width of the device's screen.
div:b is for the width of the input label. This div can be omitted too, but I would like to keep it and it's width is set to auto so that it can be wide according to the width of the label text.
I would like to set the width of the input field in a way so that it can cover the rest of the parent div (div:a) space.
Both div:b and div:ba are set as inline:block. I don't want to set any fixed width to any of the three divs as I want to make this layout flexible to any device screen (pc or mobile screen of different widths).
Here is the css and html code of the divs:
div.a{
width: 100%;
border: 1px solid red;
}
div.b {
display: inline-block;
width: auto;
height: 100px;
padding: 5px;
border: 1px solid blue;
background-color: yellow;
}
div.ba {
display: inline-block;
height: 100px;
padding: 5px;
border: 1px solid blue;
background-color: yellow;
}
<div class="a"><div class="b">Name:</div><div class="ba"><input type="text" /></ba></div>
Please note that, there will be other fields too below this input field (name) as this layout will be used to create a user input form.

Possible to make parent honour width of child image?

I am trying to make a parent element honour the width of a child image.
It works on load, but if you resize the height of the viewport to force a change in the image height, the parent element 'remembers' the initial size of the image and maintains that width.
If you mimic the above with width instead of height, there is no problem.
Here is a video of the behaviour: http://jmp.sh/8VEOZS8
Here is a codepen: http://codepen.io/iamkeir/pen/YWgvdw
html, body { height: 100%; }
.wrapper {
display: inline-block;
height: 100%;
border: 1px solid black;
}
img {
height: 100%;
}
<div class="wrapper">
<img src="http://placehold.it/1280x960" />
</div>
I'm interested to know:
1) why this is happening
2) if there is a way to fix it
Thanks!
You can fix it by setting max-width and max-height attributes to the image so it wont overflow the wrapper or the window. Then you can set the display: inline-block; to the wrapper instead which is nowadays used in replacement of floating elements. I set the image to be display: block; just so it will display it as a block element and eliminate weird space around it etc.
html, body { height: 100%; }
.wrapper {
display: inline-block;
border: 1px solid black;
}
img {
display: block;
max-width: 100%;
max-height: 100%;
}
<div class="wrapper">
<img src="http://placehold.it/1280x960" />
</div>

inline-block scrollbars when browser resized

Here is my css:
.contain
{
min-width: 300px;
background: black;
height: 200px;
display: inline-block;
overflow: auto;
}
.inl1{
/* margin: 5px 5px 5px 5px; */
min-width: 300px;
background: blue;
width: 400px;
height: 200px;
}
<div class=contain>
<div class=inl1></div>
</div>
<div class=contain>
<div class=inl1></div>
</div>
Clearly the two divs display inline, which is what I want.
However, when the browser is resized smaller the divs are displayed one above the other (desired behaviour), but once I make the browser window smaller than min-width, I need to have horizontal scrollbars displayed. This is not happening.
Any help as to why?
Edited: I tried the suggestions here, but they all seem to break the desired behaviour of the divs stacking on top of each other when the browser is sized smaller.
The effect I am after:
display the divs inline (with no scrollbars) in a browser that is wide enough; but in a "narrow" browser (ie mobile) display the divs one on top of another and THEN add horizontal scrolling ONCE the min-width can no longer be displayed for each div.
I think that's a little clearer...
You just need to have a wrapper for the divs and set it with
.wrapper{
min-width: 100%;
white-space: nowrap;
}
Here is the Fiddle: https://jsfiddle.net/1hshzxah/3/
Your outside boxes have the same minimum width as your inside ones, so both will be at least 300px wide, so no scrollbars appear. Because of the defined pixelwidth of your outer elements, your they will not stack next to each other if you do not have 600 pixels to play with or more. If you give your outer boxes a width that can scale (by using % or vw) with the page width, your result magically appears:
.contain {
width: 45%;
background: black;
height: 200px;
display: inline-block;
overflow: auto;
}
.inl1{
/* margin: 5px 5px 5px 5px; */
min-width: 300px;
background: blue;
width: 400px;
height: 200px;
}
#media all and (max-width:600px){
.contain {
width: 100%;
}
}
<div class=contain>
<div class=inl1></div>
</div>
<div class=contain>
<div class=inl1></div>
</div>
(I use 45% because I did not want to bother with floating these nicely next to each other, but you could with some more CSS). You can still add a max-width of 300 pixels to your containers to make sure they don't grow beyond 300px, but still shrink otherwise.

Can you make a child div larger than parent without position absolute

So basically what I want to do is have a div or two on a page that is larger than its parent div. Normally I would restructure the whole website however that would be a large task.
The reason I don't want them to be position absolute is that the container heights will then be screwed up and it will cause the position absolutes to overlap some divs.
The reason for the two divs being larger than their parent divs is they must be the width of the browser when the container divs can be no larger than 1200px.
Yes!
Not only that, we can do one better by using vw and calc.
Simply set the width of the child elements to be 100% of the viewport width by using vw (percentage viewport units), and then set their left margin to a negative calculated value based on this, minus the width of the wrapper. Other than the optional max-width of the parent, everything else is calculated automatically. You can dynamically change the width of the parent container, and the children will automatically resize and align as needed, without being positioned.
body,
html,
.parent {
height: 100%;
width: 100%;
text-align: center;
padding: 0;
margin: 0;
}
.parent {
width: 50%;
max-width: 800px;
background: grey;
margin: 0 auto;
position: relative;
}
.child {
width: 100vw;/* <-- children as wide as the browser window (viewport) */
margin-left: calc(-1 * ((100vw - 100%) / 2));/* align left edge to the left edge of the viewport */
/* The above is basically saying to set the left margin to minus the width of the viewport MINUS the width of the parent, divided by two, so the left edge of the viewport */
height: 50px;
background: yellow;
}
<div class='parent'>
parent element
<div class='child'>child element</div>
</div>
You can also use margins to achieve this: http://jsfiddle.net/MEc7p/1/
div{
outline: 2px solid red;
}
#outer{
width: 200px;
height: 400px;
}
#inner{
width: 600px;
height: 200px;
margin: 0 -20px;
outline: 1px solid green;
}
Try this fiddle
http://jsfiddle.net/stanze/g2SLk/
.wrapper {
width: 400px;
border: 1px solid #f00;
min-height: 153px;
}
.wrapper-child-1 {
float: left;
border: 1px solid #ccc;
width: 195%;
min-height: 262px;
}
<div class="wrapper">
<div class="wrapper-child-1"> </div>
</div>

Bottom margin of last child gets hidden when overflow applies

I have a container div which has children anchored to the bottom. The problem is that when the div's overflow scrollbar appears, the bottom margin of the last child gets hidden.
Please see http://jsfiddle.net/TxEAP/3/. At first, there's a correct margin underneath the 1 div. Clicking "append one" so that the scrollbar eventually appears makes the last div not have a bottom margin anymore. Opening DevTools shows that the margin of that last child is there, but it is outside of the container's viewport, even when scrolling completely to the bottom.
How can this be solved? It would suffice to get this working in Google Chrome.
HTML:
<div class="main">
<div class="container">
<div class="item">1</div>
<!-- several of these .item divs -->
</div>
</div>
CSS:
.main {
height: 200px;
overflow-y: scroll;
position: relative;
border: 1px solid black;
}
.container {
width: 100%;
max-height: 100%;
position: absolute;
bottom: 0;
}
.item {
padding: 20px;
margin: 15px;
border: 1px solid black;
}​
Here's my final solution using flexbox. It's supported well enough on Chrome despite all -webkit- prefixes. Basically, the idea is to have a dummy element that, in case of no overflow, fills up the space of the container starting from the top (so that the real children are anchored to the bottom); in case of overflow, it is hidden automatically because of height: 0. It does not suffer from the margin issue, and it does not collapse margins.
http://jsfiddle.net/mCYLm/1/
HTML:
<div class="main">
<div class="gap-filler"></div>
<div class="item">foo</div>
<!-- more `div.item`s -->
</div>
CSS:
div.main {
display: -webkit-box;
-webkit-box-orient: vertical;
height: 200px;
overflow-y: scroll;
}
div.main div.gap-filler {
-webkit-box-flex: 1;
height: 0;
}
div.main div.item {
border: 1px solid black;
margin: 20px;
padding: 20px;
}​
Edit: This was a solution without flexbox, but it had selection issues.
A solution that eventually worked was the following: http://jsfiddle.net/TxEAP/7/. This appends hidden "content" which makes Chrome not hide the margin of the last .item div.
.container:after {
content: "";
font-size: 0;
display: block;
height: 1px;
}
Edit: The following only works if display: inline-block is possible.
Finally I found a solution. If all .items have display: inline-block except the first one, then the margin does not get hidden.
http://jsfiddle.net/TxEAP/5/
.item:not(:first-child) {
display: inline-block;
/* attempt at getting `width: auto` like `display: block` has */
width: -webkit-calc(100% - 2 * 15px);
box-sizing: border-box;
}
If you just move the overflow-y: scroll; from .main. to .container class then the margin is preserved. The only drawback is for less than 3 items (for the given container height) you get a small scrollbar placeholder, instead of a full height one.
Removing max-height:100% on the container seems to fix it for my test in Chrome 21.
Moving the properties so that the overflow is on the container, preserves the margin/padding for an element added to the end that results in the scrollbar appearing.
.main {
height: 200px;
border: 1px solid black;
}
.container {
width: 100%;
height: 100%;
overflow-y: scroll;
}