Why is padding right clipped with overflow:scroll - html

In the snippet below, padding-right for .ctr is not visible when content starts to overflow at small viewports.
I've read other answers and I know how to fix it.
I just need to move padding:20px from .ctr to .row. Or just add margin-right:20px to last child.
But, I couldn't find the reason as to why this happens. Could someone please explain, what's going on? any resource for further learning will be highly appreciated 🙏
Thanks!
.ctr {
display: flex;
overflow-x: auto;
padding: 20px;
}
.row {
margin: 0 auto;
display: flex;
}
.child {
margin-right: 20px;
width: 600px;
height: 100px;
background: red;
}
.child:last-child {
margin-right: 0;
}
<div class="ctr">
<div class="row">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>

The padding is actually there when the content overflow it hides it.
we can illustrate this using background and background-origin
.container {
display: flex;
overflow-x: auto;
padding: 20px;
width: 200px;
background: linear-gradient(red, red) no-repeat;
background-origin: content-box;
border: 1px solid;
}
.overflow {
background: pink;
min-width: 400px;
height: 100px;
border: 1px solid;
}
<div class="container">
<div class="overflow"></div>
</div>
the white space you see on the edges is the padding
background-origin: content-box; makes the background exclude border and padding which will show us that the padding isn't clipped only covered, this happens because padding is part of the parent and the content overflow the parent so it covers it.
There's nothing special about this.

Dude the reason is the rendering or calculation in browsers (or the logic or system that we have developed starts from the top/left and ends at right/bottom). So, padding the hierarchy of placement is:
margin > border > padding > content
(And, remember it starts with top/left).
Now the issue you are seeing is only because you have not increased the height of item. If you do so - You will not only find issue on the right-padding but also on the bottom-padding.
Padding is only an effort to wrap something which is flexible. When you give a 600 * 5 width to items then they take more width than available.
padding is not as strong contender like margin. Because, margin you apply on same element - whose width or height you are manipulating. padding is being applied on an element which is trying to impose restrictions on some other element (usually direct child). So, this is the difference between padding and margin and how they get applied on browsers via Box-Model.
Hope, this clarifies a bit.

Related

Third div automatically floating

I can not understand how css works, and it's annoying me. I was trying to do some basic side by side two divs and one div below them.
At first I've learned that I had to give float:left for both side by side divs. For curiosity I did'nt gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Then I gave float:left for the second side by side div, and I came across this layout:
(source: imge.to)
Question: I didn't gave float:left for third div but it didn't act like the first screen shot. Why?
css code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
float: left;
}
.other-posts {
width: 25%;
background-color: #00ff00;
float: left;
}
.author-text {
background-color: #ffff00;
}
html code:
<div class="container">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
<div class="author-text">author text</div>
</div>
When you use a float, you break the natural box-model behavior of the markup.
Your first floated element has a width of 50%, relative to the parent (1000px) it will take the half of the .container. The second (floated) element will take the next 250px. And here comes the good thing.
The third element, which isn't floated, is also a div, thus a block-level element (so implicitly it will take 100% of the width of its parent). If you set the background-color of your first and second element to a transparent one #0000ff00 and #00ff0000 respectively. You will see your third element is growing behind them.
This is, what I mean with "breaking the box-model". Now, to understand this beter, you could start giving a explicit width to the third element. Let's say: 90%, you will see how the yellow background will reduce itself from the right side.
If you set the width to 50% it will "jump" down, to the second line. It will be even broad as the first element, but two times height. With other words, it will try to fit in the first available space.
To avoid this, in the past, we used the clearfix hack... but since flexbox and css grids are broadly supported, we don't have to rely in floats anymore for this side-by-side layouts.
Float has their own use cases, is not that float sucked, it's just not meant for layout.
For more information on this topic you can check this great article about floats on CSS-Tricks.
Wrap the items you want side by side in another wrapper, then apply flexbox to that wrapper:
.my-flex-wrap {
display: flex;
}
Then remove all the floats. Done.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.my-flex-wrap {
display: flex;
}
.blog-posts {
width: 50%;
background-color: #0000ff;
}
.other-posts {
width: 25%;
background-color: #00ff00;
}
.author-text {
background-color: #ffff00;
}
<div class="container">
<div class="my-flex-wrap">
<div class="blog-posts">dend endje denjde akdlsd gsjgıdg sadsujrg spsadnajd asdnsajdd</div>
<div class="other-posts">extra dummy text</div>
</div>
<div class="author-text">author text</div>
</div>

Position divs as follow without float

I have a web page which looks like this :
I would like to know if it is possible to have different margin-top value for the 2 outer divs. At the moment, whether I set margin : x% or margin : [value]px both outer div will receive the value from the margin. I would like it to affect only the one I set.
I mention without float because I was having problem with float and margin / width properties, but if you can come up with a proper solution using float, that'll float my boat. :)
Thanks a lot.
I'm a CSS newbie by the way so be easy on me
do you mean something like this ?
JSFIDDLE
html
<div class="container">
<div class="aaa">first</div>
<div class="bbb">second</div>
<div class="ccc">third</div>
</div>
<div class="container">
<div class="aaa">first</div>
<div class="bbb">second</div>
<div class="ccc">third</div>
</div>
css
div:not(.container){
margin: 10px 20px 30px 20px;
background: white;
height: 100px;
}
.container{
float: left;
background: black;
padding: 20px;
width: 200px;
margin-top: 25px; /*sets both divs same top*/
}
.container:not(:first-child){
margin-left: 50px;
/*margin-top: 25px*/ /*sets only second div or all others down and leaves
the first div like it is. but this for you have to
delete the margin-top entry from .container{ */
}
but actually i would use diffrent classes for this so you can set every div with his own css configuration :)
like:
.myFirstDivContainer{
/* pos data here */
}
.mySecondDivContainer{
/* pos data here */
}
and so on
EDIT
see :not() compabilitys
you can also use :nth-child() like
div.container:nth-child(0){
/* data for your first div */
}
div.container:nth-child(1){
/* data for your second div */
}
and so on...
you can use multiple css classes in the class attribute on an html element:
<div class="outer-div-wrapper">some content</div>
<div class="outer-div-wrapper larger-margin">some content</div>
then put in place some css rules:
/* this will give all divs with class 'outer-div-wrapper' a margin-top of 10px */
.outer-div-wrapper {
margin-top: 10px;
display: inline-block;
margin-right: 10px;
}
/* This will increase the margin size for the divs with the extra 'larger-margin' class */
.outer-div-wrapper.larger-margin {
margin-top: 15px;
}
Something just as good as margin-top in your case might be:
.second-div {
position: relative;
top: 15px;
}
This will move the second div 15px down relative to its default position.
BTW, you should get used to JSFiddle, it's a very good prototyping tool, and far better than making non-interactive drawings :)
Here's your drawing as a fiddle!

div with margins & padding that needs to fill its parent

I have a container div (it has both width an height set in pixels).
Is there a way to add a child div that will fill its entire parent but still have margin and or padding ?
suppose the parent div is 200px wide, and 200px high.
if I give the child div a width/height of 100% then it assumes that I mean for the content are to be of size 200px and then if I add padding or margins the size of the child becomes bigger then that of the parent.
I want the child div's content area to be what ever is left after taking out 5px margins on each side...
and please don't tell me to subtract 2*5px from 200px - I know that but I am looking for a better solution.
could it be that css can't handle such a simple task...
You could try the following:
#outer {
width: 200px;
height: 200px;
background: blue;
position: relative;
}
.inner {
position: absolute;
top: 5px;
right: 5px;
bottom: 5px;
left: 5px;
}
demo: http://jsfiddle.net/wYNYh/1/
Set all elements to have box-sizing as border-box in your stylesheet.
This will sum up the padding of all elements so you don't have to worry about any disruptions if you add any padding.
*{
box-sizing: border-box;
}
Something like this: http://jsfiddle.net/Rnf82/ ?
You can set the padding of the outer div. Then the inner div will only occupy what's left.
Have a look at this: (try yourself at jsFiddle)
.outer {
width: 200px;
height: 200px;
background-color: #DD0000;
padding: 5px;
box-sizing: border-box;
}
.inner {
width: 100%;
height: 100%;
background-color: #0000DD;
}
<div class="outer">
<div class="inner"></div>
</div>
really these two ways of doing this is equivalent as far as the question is concerned. It is important to remember the redundancy generated by how html and css standards are setup.

inline-block elements are line breaking for seemingly no reason?

I have some pretty basic HTML/CSS that isn't working as I expect. Basically I have my body setup to be 400px wide. I then have two divs inside of the body with explicit widths of 300px and 100px. Additionally, both of these divs are set to display: inline-block. For some reason, the 100px div breaks out of the body's content area and appears below it. I don't know why this is happening. If I set the width from 100px to 96px, it works. However, if I set it to 97px, 98px, 99px, or back to 100px, it doesn't work. I find this behavior very odd. Can someone explain what is going wrong?
Note that I am testing this on Chrome (Beta Channel). Code is below.
The CSS:
body {
margin: 4px;
width: 400px;
height: 250px;
border: 1px solid black;
}
.list-container {
display: inline-block;
width: 300px;
height: 100%;
background-color: red;
}
.button-container {
display: inline-block;
width: 100px;
height: 100%;
background-color: blue;
}
The HTML:
<body>
<div class="list-container">
</div>
<div class="button-container">
</div>
</body>
It's because of the way white-space collapses in html.
If you remove the line-breaks from between the two div elements, everything's fine:
<div class="list-container">
</div><div class="button-container">
</div>
JS Fiddle demo.
You could, also, just comment-out the between divs:
<div class="list-container">
</div><!--
--><div class="button-container">
</div>
JS Fiddle demo.
Or even set the font-size to zero for the body element (but you'll have to redefine it for the child elements, obviously:
body {
margin: 4px;
width: 400px;
height: 250px;
border: 1px solid black;
padding: 0;
font-size: 0;
}
JS Fiddle demo.
Another possibility with odd inline-block behaviour in Chrome is if you have text-render: optimizeLegibility set. I was struggling with inexplicable line-breaks in inline block elements in Chrome, and found that removing text-render: optimizeLegibility fixed the problem.
I've had at least one other hard-to-figure-out problem (inexplicable non-rendering of web fonts) that turned out to be caused by optimizeLegibility in the past, so from now on that's going to be a prime suspect when things behave strangely in Chrome.
(nb. Even if you don't think you're using it, if you're using a framework like Twitter Bootstrap you may be using it unwittingly)
It's the margin in your body:
margin: 4px;
Because the margin counts as part of the total width. 300px for the first one + 100px for the second div + 8px (4 on either side) for the margin = 408px. That forces the second div down to the next line.
I'm actually kind of surprised that it works at 96. It acts like it's only accounting for the margin on one side. I'd expect it to only work at 92 or below. Either way account for the margin size in the width of your body or set the margin to 0 and that should fix the problem.

unexpected margin with very simple html

I have a very simple html. The red div is inside the blue div and has a 10 px top margin. On non-ie browsers, the blue box is 10 px apart from the top of viewport and the red div is at the very top of the blue div. What I expect is the ie behavior: red div must be 10 px apart from the top of the blue div. Why does non-ie browsers render like this? (I suppose the wrong behavior is the IE's but why?)
And, what is the correct way to do this?
why blank? http://img92.imageshack.us/img92/7662/blankmr7.jpg
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>
As much as strager's answer already explains about as much as you need to know as to why it happens – namely that it happens the way it does in browsers other than IE because the specs say so – I think he picked the wrong quote from the section of the CSS 2.1 specification about collapsing margins.
The point he quoted explains how margins can collapse, not how they can "move" to a parent element.
This is rather what explains it:
If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it. In this case, the position of the element depends on its relationship with the other elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as the parent's.
Or, in slightly more human-readable form in the Mozilla developer documentation:
Parent and first/last child:
If there is no border, padding, inline content, or clearance to separate the margin-top of a block with the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block with the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.
As for how to fix it, I'd probably go for the overflow: auto solution Chris Lloyd suggested (as much as that may have side-effects).
But then that really depends on what exactly the rest of your code looks like. In this simple example you could easily just change the margin on the child element to a padding on the parent element.
Or you could float the child element, or absolutely position it...
Or how about an inverse clearfix if you want to get really fancy:
.outer:before {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
The margins are being merged. The output produced by IE is probably incorrect.
In the specifications (which are down for me at the moment):
Two or more adjoining vertical margins of block boxes in the normal flow collapse. The resulting margin width is the maximum of the adjoining margin widths.
You can use borders instead of margins, with border-color set to transparent.
There is a pretty fitting answer to this question: overflow: auto;
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
overflow: auto;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>
Could it be IE sees the DOM as div.inner having div.outer as it's parent node(and calculates offset from it),
and that other browsers instead has both of them answering to the body element?
Ok, solution without overflow auto:
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
border: 1px solid transparent;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
padding: 0;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>
The inner element is wanting something to push against, and providing a boder (or forcing the browser to consider the overflow) does this.