I am using Bourbon Neat grid to size the widths of various divs on a web page.
default.html
<main class = "default-content">
{{ content }}
</main>
default.scss
main {
#include span-columns(6);
}
page.html
The content of this page will be pipelined to {{ content }} in default.html
<div class = "full-width">
</div>
page.scss
.full-width {
#include span-columns(6);
border: 1px solid #111;
}
Expected and Desired Results
The width of <div class="full-width"> will be the full width of the parent div.
Actual Results
The width of <div class="full-width"> is only half the width of the parent div.
Conclusion
It was my impression that the child div would be the full width of the parent div since they are both #include span-columns(6). My guess is that this is not the actual result because
These divs are not within an #include outer-container
There is something in the syntax of Bourbon Neat I am missing
Something with the pipelining of the content is messing with the grid
Also, if you know ... is the use of #include outer-container necessary?
From Neat documentation
Specifies the number of columns an element should span. If the
selector is nested the number of columns of its parent element should
be passed as an argument as well.
If your $grid-columns variable is 12, in your .full-width expression, span is assumed to me 6 columns over 12 (half the size of the parent).
Correct expression is :
.full-width {
#include span-columns(6 of 6);
border: 1px solid #111;
}
Related
I've been doing CSS for a while now but couldn't figure out what's going here. Feeling really dumb :) Could you explain the behaviour?
.parent {
display:inline-block;
}
.child {
border: 2px solid red;
padding: 20px; /* this works as expected */
padding: 20%;
box-sizing: border-box; /* makes no difference */
}
<div class="parent">
<div class="child">CSSisAwesome</div>
</div>
You are facing a cyclic calculation due to the use of percentage value. The parent is an inline-block element so its width is defined by its content and that same content is using a percentage value so the content need a reference for that percentage which is the width of the parent. You have a cycle.
In such case, the browser will first ignore the padding to define the parent width and then calculate the padding BUT we don't get to calculate the parent width again because will have an infinite loop.
Check this:
.parent {
display: inline-block;
}
.child {
border: 2px solid red;
}
<div class="parent">
<div class="child">CSSisAwesome</div>
</div>
<br>
<br>
<div class="parent">
<div class="child" style="padding: 20%;">CSSisAwesome</div>
</div>
Note how in both cases, the width of the parent is the same and that width is defined by the content. The padding is added later and create an overflow.
You can find mode detail in the Specification
Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency.
Related questions:
Why does percentage padding break my flex item?
CSS Grid - unnecessary word break
How percentage truly works compared to other units in different situations
As seen in this CSSTricks article, padding using percentage units is in relation to the parent container, not the content within the element. The 20% padding you're setting in your code snippet is in relation to the .parent div's dimensions, not in relation to the content within the .child div.
If you are using % as a unit, Parent should have fixed width and height
If I have very nested HTML code that looks something like this:
<body style="margin: 8px;">
<div>
<div>
<div>
Some content...
</div>
</div>
</div>
</body>
...and I want the innermost div to span the entire width of the screen on smaller devices, up to a maximum width, but not ignore the margin of the body, how can I best do that? If I set the width of the innermost div to 100%, it has no effect because the other divs are only as wide as their content, but if I set the innermost divs width to 100vw, then it ignores the margin of the body. Is there a simpler way than setting the width of all divs so that I can use %?
div elements are block-level elements, that means that they will be the full width of their parent container by default. Unless there are styles in the parent div elements that override this behavior, your innermost div will be full width while respecting any margin values of its ancestors.
If you have styles in the parent elements that override the block behavior, then you'll want to undo those changes for mobile sizes. This can be achieved using a media-query in CSS.
Here is a contrived example.
body {
margin: 8px;
border: 1px solid black;
}
.less-width {
width: 50%;
background-color: lightgrey;
}
#media (max-width: 450px) {
.less-width {
width: auto;
}
}
<body>
<div class="less-width">
<div>
<div>
<div>SomeContent</div>
</div>
</div>
</div>
</body>
How it works
The #media property of CSS takes in arguments where you can define the condition in which the nested styles will be applied. A common pattern is to check for screen width, and to write styles for mobile views with a max-width argument passed.
Inside the media query, I created a style rule that targets the ancestor of the content and sets its width back to the default behavior with auto.
If your actual code has all div elements as ancestors all the way up to the body, then you will want to look for style rules that override this behavior (such as flex, width, or display), and undo those styles in a media query.
If there are other elements as ancestors to your content, check that these elements are block-level elements. For example, a span is not a block-level element, so it will not take up the full width by default.
Hi guys I am working on building a project where the child divs each individually have the full-width of the container, display inline, much like an inline navigation menu. Each individual child element has a width containing the full extent of the parent, however only one element at a time is shown. I have completed this, but have completed it in a way which is highly inefficient, I used an empty space html character to achieve the effect.
Here is the code I have used:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.parent > div{
display: inline;
}
/*all child divs are displayed inline */
.parent{
width:20%;
position: relative;
overflow:hidden;
border:solid;
}
/* The parent container is going to be part of a dynamic jquery carousel so I have given the width a percentage
*/
/*width does not apply to inline elements*/
.children{
position: absolute;
width: 100%;
}
/*class to specify attributes shared by all the child divs of the parent container*/
.child-1{
background-color: #8A2BE2;
}
/*First child div*/
.child-2{
left:100%;
background-color: #FF7F50;
}
/*second child div*/
</style>
</head>
<body>
<div class="main-parent">
<div class="parent">
<div class="children child-1">
First child
</div>
<div class="children child-2">
Second child
</div>
</div>
</div>
</body>
</html>
The menu items don't necessarily need to stay 'in line' since you are showing them one at a time anyway.
It's easiest if you follow an approach like this - all the navigation items are block full width elements, and you setup the height of the wrapper to be equal to a single nav item, and via javascript you play with the vertical positioning such that the one that you want comes into view (rather than play with the left variable of an absolute positioned element).
I think that if it's difficult for you to explain a concept, it will be probably even more difficult for a user to use your solution, so maybe a trip to the drawing board and see what details might be missing would do you good.
I have a fixed width container <div> that displays one or more widget <div>s. I want it to look like this:
<- grey blocks are widgets, red border is the container
Simplified, my structure in HTML looks like this:
<div id="container">
<div id="widget1">1</div>
<div id="widget2">2</div>
<div id="widget3">3</div>
<div id="widget4">4</div>
<div id="widget5">5</div>
<div id="widget6">6</div>
<div id="widget7">7</div>
</div>
Considerations
Widgets will have a fixed height e.g. 100px
Widgets will have a fixed width e.g. 100px but they may also be a multiple of that width (plus any margins crossed - see widget 1)
Widgets should be spaced nicely with a margin (or similar) e.g. 10px
I don't know how many widgets there will be (the user can assign as many or few as they like to the container).
The container is a fixed width but doesn't have any "visual" styling (the red border is there for demonstration)
Solution has to work in modern browsers (and MSIE7) and would ideally be pure CSS.
Because of consideration 4. I can't assign additional markup e.g. row div, classes (.first-child, .last-child) and because of 2. :nth-child wouldn't work AFAIK.
Things I've tried
margin-left on widgets with :first-child setting margin-left: 0 won't display a new row properly.
margin-right on widgets with :last-child setting margin-right: 0 the first row forces the container div wider and last-child isn't supported until MSIE9.
equal left and right margins (e.g. margin: 0 5px 10px) forces the container wide again.
overflow - works great in my head! Not so much with either margins or padding.
Is there a way to do this in CSS?
http://jsfiddle.net/agtb/VHXGT/
I believe you are thinking too complicated :-)
If I understand you correctly you don't need any special handling of the separate widgets. Just give the widgets an all around margin of half the spacing, and the container the same margin but negative.
#container {
width: 440px;
margin: -5px;
}
#container div {
background-color: gray;
height: 100px;
width: 100px;
float: left;
margin: 5px;
}
See http://jsfiddle.net/SGdG3/1/
set container width 400 and the first div width 200 float left, rest width 100 float left
Suppose I have this HTML structure:
<div class="a">
<div class="floated-left">...</div>
<div class="floated-left">...</div>
</div>
I have noticed that if I don't set overflow:hidden to .a, then the <div class="a"> does not occupy any vertical size. For example, if I set its background to red, it is not visible at all. Inspecting it with FireBug shows that it's there but of almost no vertical size.
To fix this, I found that I have to set overflow:hidden to .a. Then the first <div> goes over all its content.
Here is a real example:
<html>
<head>
<style>
.a { background-color: red; }
.b { background-color: red; overflow: hidden }
.floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
</style>
</head>
<body>
<p>div with class a, that doesn't overflow:hidden:</p>
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
</div>
<div style="clear:both"></div>
<p>div with class b, that does overflow:hidden:</p>
<div class="b">
<div class="floated-left">Hi,</div>
<div class="floated-left">Dad!</div>
</div>
</body>
</html>
Notice how Hi, Mom! does not get red background (no overflow:hidden), while Hi, Dad! does get red background (has overflow:hidden).
Can anyone explain this behaviour?
Here is screenshot of the example:
Thanks, Boda Cydo.
When you float elements they are taken out of the document flow. Among other things, this means that they have no impact on the dimensions of the parent element (although its width will determine where the floats are positioned on the horizontal axis). They do however impact positioning of siblings within the container depending on whether those sibling are inline or block level elements and whether they have width or not.
In order to make the height of the floats impact the height of the container you must have an element after them that clears them. However, what you are seeing here is actually a part of the CSS standard that you can use to clear floats without additional, non-semantic markup. The only issue is this behavior can vary slightly in older browsers and their css implementations. This effect is present with both overflow auto and overflow hidden but does not present with overflow visible. In IE < 6 you must have a width set on the containing element for it to work.
Hi, Mom does not get any background because the background comes from the a div, which is height 0 (or near 0). The inner divs are actually overflowing its bounds (which is what floats do by default).
The thing to remember with floats is that they don't have inherent height (when it comes to layout and determining the parent's height). Inline content simply flows around them. So without overflow: hidden the parent div has no height. No height means no background. The floats are still rendered but they go beyond the bounds of the parent div ie the content in the floats is outside the parent div.
Floated elements don't occupy any vertical space for clearing, there are a few ways to fix this, something like:
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
<br style="clear: left;" />
</div>
Would clear after, and make the outer div have a vertical height. Set a border: solid 1px red; on .a to see this in action.
Alternative CSS only solution:
.a:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
Per the spec for CSS basic box model:
Margins of a floated box do not
collapse with any other margins.
Margins of a box with ‘overflow’ other
than ‘visible’ do not collapse with
its children's margins.
By providing it the "overflow" property explicitly you have allowed the children to fit into this model, thus the b div no longer has bounds attached to its children. If you apply visible or inherit (which the parent of b is visible by default), the bounds return and the children divs define the margins.
http://www.w3.org/TR/css3-box/ (RE: Example X)