Negative margin-right with left floats in the parent container - html

Learning CSS basics and was doing layouts with floats. I know CSS Grid and Flexbox are best practice and I intend to learn them, but wanted to understand the basics of floats before I move on.
body {
margin: 0px;
padding: 0px;
}
.wrapper {
width: 600px;
padding-left: 200px;
padding-right: 200px;
overflow: hidden;
}
.col-main {
float: left;
width: 100%;
}
.col-left {
position: relative;
float: left;
width: 200px;
margin-left: -100%;
right: 200px;
}
.col-right {
float: left;
width: 125px;
margin-right: -125px;
}
<body>
<div class="wrapper">
<div class="col-main">Main Content</div>
<div class="col-left">Left Content</div>
<div class="col-right">Right Content</div>
</div>
</body>
On an intuitive level I understand how .col-left works. margin-left: -100%; represents 600px width of the parent element placing it along side .col-main and position: relative; combined with right: 200px; puts it flush within the reserved left padding of the parent element. In fact, it doesn't have to be -100% it can be -200% if you like and push .col-left completely off the screen.
However, I cannot grasp how .col-right works. Having a negative value in margin-right that's equal to the absolute value in width places the .col-right on the same line, neatly sticking out on the right side of the parent element. It's great but I don't understand how or why. What's more, is that if you change margin-right to -200px or heck even -1000px it will still be in the same position. Why?

Float's meaning is basically floating :). You can insert value How much you want. But in the end it floats to right. Because wrapper's width not enough to changing to your see. if you add more width to wrapper and specify scalable value to .col-main (like 50px). You can see more understandable. Because .col-right is in over .col-main. like z-index shits

Related

Fixed Sidebar Within Container With Fluid Content

I'm trying to achieve a fixed left sidebar with fluid right content within a container.
I've checked out answers that tell me to set a margin-left on the content which is not what I want to do.
The closest I could get was through this answer:
A `position:fixed` sidebar whose width is set in percentage?
<div class="main-container">
<div class="sidebar">
<div class="sidebar-content-container">
<div class="sidebar-content">
<!-- Sidebar content here -->
</div>
</div>
</div>
<div id="content">
<!-- Scrollable Content Here -->
</div>
</div>
This is the CSS
.main-container {
height: 100vh;
max-width: 1366px;
margin-left: auto;
margin-right: auto;
padding-left: 15px;
padding-right: 15px;
padding-top: 100px;
width: 100%;
position: relative;
.sidebar {
float: left;
width: 20%;
height: 100%;
position: relative;
.sidebar-content-container {
height: 100%;
position: fixed;
.sidebar-content {
display: block;
height: 100%;
width: 100%;
overflow: hidden;
}
}
}
#content {
height: 100%;
width: 80%;
display: inline-block;
float: right;
}
}
The way I have it done right now, once you inspect the sidebar, the width it calculates is not within the main-container but the rest of the viewport. What I'm trying to achieve is to keep the 20% calculation within the main-container without setting a fixed width.
So the yellow part represents the problem for me. Once I set it fixed, it doesn't stay within the parent container. My goal is after I set it to fixed, it stays within the red part.
I know I could do something like sidebar width 100px content margin-left 100px but that's not the objective and do not like any javascript alternatives.
Thoughts?
Thanks!
Your are using width:100% in this div and also padding which increases its width from 100% because padding adds to the width. So for giving the padding within the 100% width you can use property box-sizing:border-box as below:
.main-container {
height: 100vh;
max-width: 1366px;
margin-left: auto;
margin-right: auto;
padding-left: 15px;
padding-right: 15px;
padding-top: 100px;
width: 100%;
position: relative;
box-sizing:border-box;
}
Well, I guess that's the thing with fixed elements. They kind of have a mind of their own. Once an element is fixed, it doesn't seem to obey the overflow and dimension rule of its parent containers. They take their dimensions (if you are using %) from the browsers width. So I think what you should do is to give the fixed element the same dimension as its immediate container.
<div id="parent-box">
<div id="fixed-elem"></div>
</div>
//css
#parent-box{
position: relative;
width: 40%;
height: 100%;
float: left;
overflow: hidden;
}
#fixed-elem{
position: fixed;
width: 40%;/*this is 40% of the browser width not the container*/
height: 100%;/*this is 100% of the browser height*/
}

Header div obeying sibling container div's margin. Very confused

I have a very simple structure and layout.
There is a #header and a #footer with a #body-container between them. The #header is position: fixed.
The #body-container has a margin-top: 3.1em to make room for the #header, which has height: 3em, but that doesn't work the way I thought it would. Even though the #header is not a child of the container, it won't render above the container (i.e. in the margin).
Why doesn't the #header render in the top margin of the #body-container? How can I achieve the desired effect?
You can fiddle with it here, and the code is here for reference:
HTML:
<body>
<div id="header">
</div>
<div id="body-container">
<div class="left">
</div>
<div class="right">
</div>
</div>
<div id="footer">
</div>
</body>
CSS:
div {
margin-bottom: 0.1em;
background-color: #99ccff;
}
#body-container {
background-color: white;
margin-top: 1.1em;
width: 20em;
height: 35em;
}
.left {
width: 2.5em;
height: 100%;
float: left;
}
.right {
margin-left: 2.6em;
height: 100%;
}
#header {
background-color: #99eeee;
position: fixed;
height: 3em;
width: 20em;
z-index: 1;
}
#footer {
height: 3em;
width: 20em;
}
That's an interesting effect. It seems that the #body-container pushes the edge of the body up and it affects the placement of the fixed header. This is happening because the header is set without coordinates. Add the following rule set to place the header at the very top of the page:
#header {
top: 0;
left: 0;
}
Another way to prevent the margin of the #body-container affect the placement of the header is to set the padding on the body element. The rule set below will eliminate the effect of the margin-top of the #body-container and keep the fixed #header aligned with the other content, if coordinates are NOT used for the #header.
body {
padding: 20px;
}
The effect is called "margin collapse," which is discussed in this thread as well. Margin collapse behavior is specified and expected.
There are a few ways to the desired effect I've learned about since asking. Working jsfiddles are linked:
Add negative margin-top to #header.
This feels cleanest to me.
Move the #body-container's margin-top to padding-top.
This is bound to mess with some of the possible CSS style/layout properties if things get complex, and it does leave a gap between the top of the page and the header.
Exactly specify the #header coordinates with top and left properties.
See #DRD's answer.
Add any nonzero padding to the body.
Again, see #DRD's answer.

Fluid sidebar on left with content on right; won't float next to each other with 100% width

I'm having an issue with a fluid sidebar and a content box next to it.
I designed my left #sidebar to my liking, but not I'm having trouble making a content box that fills up the remaining space next to it.
I'd like to have the whole project take up 100% of the page width. The problem is coming from the min/max widths on my sidebar.
Been goin' hard on this all day and still having problems, void space between, overlapping ,ect.
http://jsfiddle.net/DrDavidBowman01/PjLgE/
CSS
#container {
width: 100%;
display: block;
height: 100%;
}
#sidebar {
display: block;
width: 22%;
float:left;
min-width: 236px;
max-width: 332px;
height: 100%;
position: fixed;
border: 2px solid #0C6;
background-color: #000;
}
#content {
width: 88%;
height: 400px;
border: 6px solid #F00;
display: block;
color: #fff;
float: left;
position: relative;
max-width: calc(88% - 236px);
min-width: calc(88% - 332px);
}
HTML
<div id="container">
<div id="sidebar"></div>
<div id="content"></div>
</div>
It's a combination of two things. First, if you want to have divs take up 100% height, then you'll need to set the body and html to that as well.
html, body {
height: 100%;
}
Second, you have set the sidebar as position: fixed. This is just like having position: absolute set on it. If you want the sidebar to remain visible at all times, you can do a margin-left: 22%; (or whatever the width of the sidebar is) on #content. If you want the sidebar to flow with the rest of the page, just remove the fixed position.
This is because your sidebar is position: fixed. The best route would be to relatively position/float the sidebar at 100% height and position a fixed wrapper within it.
basic demo

related to float and width

I have a sidebar and a content area. I just floated the sidebar to the left and the content area to the right. But I have problem when the screen size changes. There occurs a significant space between the two floats. I think it's due to the size of the image in the content area and since it's floated right. Hence I floated this content area also to the left. now the content area is not extending to the extreme right end of the screen. Is there any way to put the content area fit in the right portion without any space (just the space to divide the sidebar and content area is enough)?
If you need more explanations, please let me know.
Change your CSS to this:
.dashContent {
float: left;
margin: 10px;
position: relative;
top: 25px;
min-width: 80%;
}
.sidebarDash {
float: left;
height: auto;
width: 195px;
}
This will remove the space and also retain fluidity in the layout - Removed as the OP wants a fixed layout
Place .sidebarDash with adsolute position and give padding-left the same as sidebar width to .dashContent
Wrap these two in one main DIV as -
<div class="dashContainer">
<div class="sidebarDash"></div>
<div class="dashContent"></div>
</div> <!-- Clears the float with CSS -->
CSS -
.dashContainer{ overflow: hidden; position: relative }
.sidebarDash { position: absolute; left: 0; top: 0; width: 200px; }
.dashContent { padding: 0 0 0 210px; }
jQuery -
Insert this in <head> section of the document -
<script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
$(function(){
var sidebarHeight = $('.sidebarDash').height();
$('.dashContainer').css('min-height', sidebarHeight);
})
</script>
Instead of using float:right use float:left so both divs stay together, have a look on this fiddle
http://jsfiddle.net/FZZnk/
Let me know if this solve your problem
First, you need to use percent to all of the divs width.
second, you can make the both float to the same side (right or left), and use margin or padding in percent to make to space between these divs.
.dashContainer{ overflow: hidden; width: 100%; }
.sidebarDash { float: left; width: 20%; }
.dashContent { float: left; width: 80%; }
Now, because your left side bar has a fix width and float left, you can do this:
remove the float right, and add margin-left at the size of your side bar.
and don't forget to set the div to width: 100%.
.dashContent {
float: right;
margin-left: 210px;
position: relative;
top: 25px;
width: 100%; }

How to set the margin or padding as percentage of height of parent container?

I had been racking my brains over creating a vertical alignment in css using the following
.base{
background-color:green;
width:200px;
height:200px;
overflow:auto;
position:relative;
}
.vert-align{
padding-top:50%;
height:50%;
}
<!-- and used the following div structure. -->
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
While this seemed to work for this case, i was surprised that when i increased or decreased the width of my base div, the vertical alignment would snap. I was expecting that when I set the padding-top property, it would take the padding as a percentage of the height of the parent container, which is base in our case, but the above value of 50 percent is calculated as a percentage of the width. :(
Is there a way to set the padding and/or margin as a percentage of the height, without resorting to using JavaScript?
The fix is that yes, vertical padding and margin are relative to width, but top and bottom aren't.
So just place a div inside another, and in the inner div, use something like top:50% (remember position matters if it still doesn't work)
An answer to a slightly different question: You can use vh units to pad elements to the center of the viewport:
.centerme {
margin-top: 50vh;
background: red;
}
<div class="centerme">middle</div>
Here are two options to emulate the needed behavior. Not a general solution, but may help in some cases. The vertical spacing here is calculated on the basis of the size of the outer element, not its parent, but this size itself can be relative to the parent and this way the spacing will be relative too.
<div id="outer">
<div id="inner">
content
</div>
</div>
First option: use pseudo-elements, here vertical and horizontal spacing are relative to the outer. Demo
#outer::before, #outer::after {
display: block;
content: "";
height: 10%;
}
#inner {
height: 80%;
margin-left: 10%;
margin-right: 10%;
}
Moving the horizontal spacing to the outer element makes it relative to the parent of the outer. Demo
#outer {
padding-left: 10%;
padding-right: 10%;
}
Second option: use absolute positioning. Demo
#outer {
position: relative;
}
#inner {
position: absolute;
left: 10%;
right: 10%;
top: 10%;
bottom: 10%;
}
To make the child element positioned absolutely from its parent element you need to set relative position on the parent element AND absolute position on the child element.
Then on the child element 'top' is relative to the height of the parent. So you also need to 'translate' upward the child 50% of its own height.
.base{
background-color: green;
width: 200px;
height: 200px;
overflow: auto;
position: relative;
}
.vert-align {
position: absolute;
top: 50%;
transform: translate(0, -50%);
}
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
There is another a solution using flex box.
.base{
background-color:green;
width: 200px;
height: 200px;
overflow: auto;
display: flex;
align-items: center;
}
<div class="base">
<div class="vert-align">
Content Here
</div>
</div>
You will find advantages/disavantages for both.
This can be achieved with the writing-mode property. If you set an element's writing-mode to a vertical writing mode, such as vertical-lr, its descendants' percentage values for padding and margin, in both dimensions, become relative to height instead of width.
From the spec:
. . . percentages on the margin and padding properties, which are always calculated with respect to the containing block width in CSS2.1, are calculated with respect to the inline size of the containing block in CSS3.
The definition of inline size:
A measurement in the inline dimension: refers to the physical width (horizontal dimension) in horizontal writing modes, and to the physical height (vertical dimension) in vertical writing modes.
Example, with a resizable element, where horizontal margins are relative to width and vertical margins are relative to height.
.resize {
width: 400px;
height: 200px;
resize: both;
overflow: hidden;
}
.outer {
height: 100%;
background-color: red;
}
.middle {
writing-mode: vertical-lr;
margin: 0 10%;
width: 80%;
height: 100%;
background-color: yellow;
}
.inner {
writing-mode: horizontal-tb;
margin: 10% 0;
width: 100%;
height: 80%;
background-color: blue;
}
<div class="resize">
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
</div>
Using a vertical writing mode can be particularly useful in circumstances where you want the aspect ratio of an element to remain constant, but want its size to scale in correlation to its height instead of width.
Other way to center one line text is:
.parent{
position: relative;
}
.child{
position: absolute;
top: 50%;
line-height: 0;
}
or just
.parent{
overflow: hidden; /* if this ins't here the parent will adopt the 50% margin of the child */
}
.child{
margin-top: 50%;
line-height: 0;
}
This is a very interesting bug. (In my opinion, it is a bug anyway) Nice find!
Regarding how to set it, I would recommend Camilo Martin's answer. But as to why, I'd like to explain this a bit if you guys don't mind.
In the CSS specs I found:
'padding'
Percentages: refer to width of containing block
… which is weird, but okay.
So, with a parent width: 210px and a child padding-top: 50%, I get a calculated/computed value of padding-top: 96.5px – which is not the expected 105px.
That is because in Windows (I'm not sure about other OSs), the size of common scrollbars is per default 17px × 100% (or 100% × 17px for horizontal bars). Those 17px are substracted before calculating the 50%, hence 50% of 193px = 96.5px.
A 50% padding wont center your child, it will place it below the center. I think you really want a padding-top of 25%. Maybe you're just running out of space as your content gets taller? Also have you tried setting the margin-top instead of padding-top?
EDIT: Nevermind, the w3schools site says
% Specifies the padding in percent of the width of the containing element
So maybe it always uses width? I'd never noticed.
What you are doing can be acheived using display:table though (at least for modern browsers). The technique is explained here.
CSS Grid with empty row
This approach probably only makes sense if you're already using css-grid for the container in question, but if you are you can create an empty row with a percentage that (because it is a row) will be a percentage of the height.
.wrapper
{
border: 2px solid red;
width: 400px;
height: 200px;
display: grid;
grid-template-rows: 10% 1fr;
}
.child
{
background: orange;
width: 50px;
height: 50px;
grid-area: 2/1;
}
<div class="wrapper">
<div class="child">
</div>
</div>