I am learning floating elements in CSS and i encountered the following peculiar behavior.
Here is the code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#one { background-color: red; width: 200px; height: 200px; margin: 10px; }
#two { background-color: yellow; width: 200px; height: 205px; margin: 10px; }
#three { background-color: lightpink; width: 200px; height: 200px; margin: 10px; }
#four { background-color: green; width: 200px; height: 200px; margin: 10px; }
#five { background-color: coral; width: 200px; height: 200px; margin: 10px; }
#six { background-color: #b1ffea; width: 200px; height: 200px; margin: 10px; }
div{
/*display: inline-block;*/
float: left;
vertical-align: central;
}
</style>
</head>
<body>
<div id="one">
First div
</div>
<div id="two">
Second div
</div>
<div id="three">
three div
</div>
<div id="four">
four div
</div>
<div id="five">
five div
</div>
<div id="six">
six div
</div>
</body>
</html>
My question is why "four div" is placed below the "third div" not first and second ?
On the other hand, if i resize the browser (see image below) why in this case it is working perfectly ?
Because the second div element is taller than the first div, the forth div collides with the second div. When the forth div drops to the next line, it starts on the right and slides left, beginning under the third div, until it collides with the second div. If you look at your code at with 4 div elements per line, the fifth div drops to the next line. It begins below the fourth div and beginning moving left until it collides with the second div, because the second div is longer that the third or fourth div elements.
This is perfectly working as usual. Height of div2 is 205px instead of 200px. Change it to 200px and it will work fine.
I adjusted the CSS margins of #two using Inspect to this...
After that change, the div elements all seemed to behave as you wanted them to when the browser's window width was adjusted.
Related
I have the following HTML code:-
<html>
<head>
<meta charset="utf-8">
<title>Personal Site</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="header1">
hello world
</div>
<div class="header2">
</div>
<div class="header3">
</div>
</body>
</html>
Below is the style defined in the style sheet:-
.header1{
background-color: yellow;
width: 35%;
height: 200px;
display: inline-block;
}
.header2{
background-color: blue;
width: 30%;
height: 200px;
display: inline-block;
}
.header3{
background-color: green;
width: 34%;
height: 200px;
display: inline-block;
}
I am getting the following output:-
Question: Despite defining my display property as inline-block, why is the yellow box along with Hello World going in the second line? If I remove the text Hello world then all three box lines up together?
Can someone please explain this behavior?
The inline-block display property treats block level elements (e.g. ) as an inline element (e.g. ), and, just like if you had a line break between two elements, the line-break between the s is creating a space between the s. That extra margin is actually a spaceānot a margin.
ref: more details...
apply 'float:left' to each header block.
.header1{
background-color: yellow;
width: 35%;
height: 200px;
display: inline-block;
float:left;
}
.header2{
background-color: blue;
width: 30%;
height: 200px;
display: inline-block;
float:left;
}
.header3{
background-color: green;
width: 35%;
height: 200px;
display: inline-block;
float:left;
}
Seems to be a quirk of inline-block. If you add vertical-align:top; it sorts it out.
.header1{
background-color: yellow;
width: 35%;
height: 200px;
display: inline-block;
vertical-align:top;
}
.header2{
background-color: blue;
width: 30%;
height: 200px;
display: inline-block;
vertical-align:top;
}
.header3{
background-color: green;
width: 34%;
height: 200px;
display: inline-block;
vertical-align:top;
}
The following is a theory, based on reading the Visual formatting model document provided by the W3C. I'm most likely wrong on at least part of this, but:
By applying display: inline-block to the div elements, the end result is
the divs themselves are inline
the content inside each div gains a, let's call it a "virtual container", that's a block element (or treated as such).
Inline elements collapse to the height and width of their content. In the second and third divs, since those are empty, means those collapse to a height of 0. The boxes you see are actually the inner content overflowing the parent divs.
The three elements all have a default vertical-align value of baseline, so I suspect what you're ultimately seeing is three divs aligned in a row, to the baseline of the first div, but then the bottom of the inner content of the latter divs is aligning to the baseline of the first div, with their tops pushing the whole row down from the top of the page.
Adding the the old "has-layout" trigger will cause the inline elements to resize to fit their content, if that's all you're after (you'll want to run this with the full-screen option to see it correctly):
.my-block{
height: 200px;
display: inline-block;
/* these rules applied together trigger hasLayout */
/* see https://webplatform.github.io/docs/css/cssom/properties/hasLayout/ */
overflow: auto;
zoom: 1;
}
.header1{
background-color: yellow;
width: 35%;
font-size: 25px;
}
.header2{
background-color: blue;
width: 30%;
}
.header3{
background-color: green;
width: 34%;
}
<html>
<head>
<meta charset="utf-8">
<title>Personal Site</title>
</head>
<body>
<div class="header1 my-block">
hello world
</div>
<div class="header2 my-block">
</div>
<div class="header3 my-block">
</div>
</body>
</html>
Changing the vertical-align to top or bottom would yield the same effect in your example, although you'd need to make sure either of those alignments make sense in your "real" code.
I have a 3 column layout which I'm creating using inline-block divs. The left and right columns are fixed widths but the inner column is to hold dynamic content and should expand horizontally as required by it's content width.
That's easy enough... the tricky part is that when the browser window is smaller (horizontally) than the width of the left, right and expanded middle divs, I would like the middle div to scroll and the side columns to stay fixed. In other words, the middle div's size should shrink and grow with window resize but should not grow beyond the available space.
Simply laying out the divs looks like this
https://jsfiddle.net/xzjp5xef/1/
HTML:
<div id="container">
<div id="lcol">
left
</div>
<div id="midcol">
<div id="spacer">
150px spacer
</div>
</div>
<div id="rightcol">
right
</div>
</div>
CSS:
div {
height:200px;
border-style:solid;
display: inline-block;
border-width: 1px;
vertical-align: top;
}
#container{
white-space: nowrap;
}
#lcol {
background-color:blue;
width: 100px;
}
#midcol {
background-color: yellow;
overflow-x: auto;
}
#spacer {
min-width: 150px;
margin: 10px;
height: 20px;
}
#rightcol {
background-color: red;
width:100px;
}
The point of the "spacer" div is to represent the dynamic content which in this case I've fixed to 150px plus padding. So in this case I want the divs to lay out the way they do in the above fiddle, but then when the window is shrunk horizontally, I want the middle div to scroll and the left and right divs to remain fully visible.
That fails because then the window gets a scroll bar but the middle panel remains the same width and the right hand div disappears into the scrolled region.
My next attempt was using absolute positioning
https://jsfiddle.net/n4zrLqh2/
I fixed the left div to the left and the right div to the right and set the middle div's right and left properties. This is a neat trick which allows the middle div to stretch and take up all available space. This works nicely but doesn't create the effect I'm after when the window is big - because I don't want the middle column to expand further than is necessary to contain its content.
In the end I've solved this with javascript but would much prefer a CSS solution.
Edit: To help others see what I'm trying to achieve, here's the complete javascript solution (which I'd prefer to achieve with pure CSS):
HTML:
<div id="lcol">left</div>
<div id="midcol">
<div id="spacer">150px spacer</div>
</div>
<div id="rightcol">right</div>
CSS:
div {
height:200px;
display: inline-block;
vertical-align: top;
margin: 0px;
float:left;
}
body {
white-space: nowrap;
margin:0px;
max-height: 200px;
}
#lcol {
background-color:blue;
width: 100px;
}
#midcol {
background-color: yellow;
overflow-x: auto;
}
#spacer {
min-width: 150px;
height: 20px;
background-color: gray;
margin: 5px;
}
#rightcol {
background-color: red;
width:100px;
}
JAVASCRIPT (with jquery)
function adjustSizes() {
// Sizes of middle divs are dynamic. Adjust once
// built or whenever the viewport resizes
//
var $leftDiv = $('#lcol')
var $milddleDiv = $('#midcol');
var $rightDiv = $('#rightcol');
// 1. Resize middle div to available viewport space
var maxBodyWidth = $(window).innerWidth() - ($leftDiv.outerWidth() + $rightDiv.outerWidth());
$milddleDiv.css('maxWidth', maxBodyWidth);
}
$(window).resize(function () {
adjustSizes();
});
And the fiddle: https://jsfiddle.net/bjmekkgj/2/
I think setting max-width of spacer will solve your problem in case content increases.
Set max-width to calc(100vw - 200px) if all margin and padding are 0. Otherwise adjust the value 200px taking margin, padding into account.
I have created a plunker. Please check if it solves your issue. Try checking after running plunker in spearate window
http://plnkr.co/edit/WG9v0MyiD2hiaZrOA3Yw?p=preview
For the one example you provided, since the left and right columns are positioned absolutely, you should take up the space somehow. I used padding on the middle column, then nested a "content" block inside that represents the visible part of the middle column. Then, I put overflow-x: auto; on the new content block and set a max-width on the overall container to force the new block to shrink.
(In previous edits, I was attempting to do this same thing but with floats instead of absolutely positioned divs)
* { margin: 0px; padding: 0px; }
#container {
box-sizing: border-box;
display: inline-block;
position: relative;
max-width: 100%;
border: 1px solid black;
height: 200px;
}
.column {
box-sizing: border-box;
height: 100%;
}
#left {
position: absolute;
left: 0px;
top: 0px;
bottom: 0px;
width: 100px;
border-right: 1px solid black;
background: blue;
}
#mid {
border: none;
padding: 0px 100px;
}
#mid > .content {
box-sizing: border-box;
background-color: yellow;
overflow-x: auto;
height: 100%;
}
#spacer {
width: 150px;
height: 20px;
}
#right {
position: absolute;
right: 0px;
top: 0px;
bottom: 0px;
width: 100px;
border-left: 1px solid black;
background: red;
}
<div id="container">
<div id="left" class="column">
left
</div>
<div id="mid" class="column">
<div class="content">
<div id="spacer">
150px spacer
</div>
</div>
</div>
<div id="right" class="column">
right
</div>
</div>
...and in JSFiddle form
flexbox can do that.
div {
border-style: solid;
border-width: 1px;
}
#container {
height: 200px;
display: flex;
}
#lcol {
background-color: blue;
width: 100px;
}
#midcol {
background-color: yellow;
flex: 1;
overflow-x: auto;
}
#rightcol {
background-color: red;
width: 100px;
}
<div id="container">
<div id="lcol">
left
</div>
<div id="midcol">
</div>
<div id="rightcol">
right
</div>
</div>
JSfiddle Demo (showing overflow effect).
Support is IE10 and up.
Try setting the middle div to have a max width with a percentage so it will get thinner with the screen size:
.midcol {
max-width: 25%;
}
I put a value for the max-width in there for an example, but you can change the value.
I've got 3 divs - Each of these in a parent div with a width of 100%. CSS:
.parentDiv {
height: 454px;
width: 100% auto;
}
.Div1, .Div2, .Div3{
display: block;
position: relative;
text-align: center;
height: 434px;
margin-top: 10px;
margin-bottom: 10px;
}
.Div1 {
margin-left: 10px;
float: left;
width: 351px;
}
.Div2 {
width: 351px;
padding: 0px;
margin: auto;
display: block;
}
.Div3 {
margin-right: 10px;
float: right;
width: 351px;
}
The Divs are ordered in the same way they are in the CSS, in the HTML.
Yet, the result of this is that the left element (Div1) is in the correct place, the supposedly centred element is centred (Div2) although it has margins either side of it that fill the entire parent Div. Therefore, I think this causes Div3 to overflow the parent Div and "collapse" vertically.
What I would really like to know is how to align the divs so that there is one on the left, one centred and one on the right. The previous questions regarding similar problems don't seem to help me in this case :/ If there was a way to shorten Div2's margins so that they could allow all of the Divs to remain aligned correctly in the parent div - I would really love to know how (Preferably not using absolute pixel measurements)
This probably made no sense - But I really do appreciate all suggestions/answers :)
Cheers
Additional Explanation:
This is what it is at the moment:
Div1Div2Div3
What I would like:
Div1 Div2 Div3
The length of this is equal to the parentDiv
HTML (For this section)
<div class="parentDiv">
<div class="Div1">
<!--Insert code here-->
</div>
<div class="Div2">
<!--Insert code here-->
</div>
<div class="Div3">
<!--Insert code here-->
</div>
</div>
SOLUTION # 1
You may see the JSFIDDLE DEMO.
HTML CODE
<div class="parentDiv">
<div class="Div1">
Div 1 - Some text
</div>
<div class="Div2">
Div 2 - Some text
</div>
<div class="Div3">
Dive 3 - Some text
</div>
</div>
CSS CODE
.parentDiv {
height: 454px;
width: 100% auto;
}
.parentDiv div{
float:left;
}
.Div1, .Div2, .Div3{
display: block;
position: relative;
text-align: center;
height: 434px;
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #c4c4c4;
}
.Div1 {
margin-left: 10px;
width: 351px;
}
.Div2 {
width: 351px;
padding: 0px;
display: block;
}
.Div3 {
margin-right: 10px;
width: 351px;
}
SOLUTION # 2
Please go through the FIDDLE DEMO.
Here is the complete source code:
I have added margin-left to all 3 divs.
Code:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<style>
.parentDiv {
height: 454px;
width: 100% auto;
}
.parentDiv div{
/* float:left; */
}
.Div1, .Div2, .Div3{
display: block;
position: relative;
text-align: center;
height: 434px;
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid #c4c4c4;
}
.Div1 {
margin-left: 10px;
width: 351px;
}
.Div2 {
display: block;
margin-left: 361px;
padding: 0;
width: 351px;
}
.Div3 {
margin-left: 714px;
width: 351px;
}
</style>
</head>
<body>
<div class="parentDiv">
<div class="Div1">
Div 1 - Some text
</div>
<div class="Div2">
Div 2 - Some text
</div>
<div class="Div3">
Dive 3 - Some text
</div>
</div>
</body>
</html>
As you will observe:
I have removed margin from Div2.
I have added new css for .parentDiv div - so you may please remove the float from other individual divs.
You may like to remove the BORDER of the divs.
My Suggestion
I suggest to use Responsive Breakpoints to make your page Responsive.
Try to do this on div2:
.Div2 {
width: 351px;
padding: 0px;
margin: auto;
display: block;
margin: 0 auto;
float: left;
}
If you want a better solution than floating elements, change it for display:inline-block elements.
.parentDiv > div { font-size: 1em; display: inline-block; vertical-align: top; }
.parentDiv { font-size : 0; }
This works responsive and is better than float. Float is only for floated elements, not for design layout. It's a false and most recurrent technique by some front-end developers. Thanks to floats, you can see thousands of tons of clearfix along the pages. It is cruft, crap.
Not to worry, managed to finally solve it using some jQuery:
$(document).ready(function(){
var width = $(".parentDiv").css("width")
var width = width.replace("px","");
var width = parseInt(width,10);
var val1 = width-1073;
var val2 = val1/2;
$(".Div2").css("margin-left",val2);
$(".Div2").css("margin-right",val2);
$(window).resize(function(){
var width = $(".parentDiv").css("width");
var width = width.replace("px","");
var width = parseInt(width,10);
if(1073>width) {
$(".Div3").css("display","hidden")
}
else {
var val1 = width-1073;
var val2 = val1/2;
$(".Div2").css("margin-left",val2);
$(".Div2").css("margin-right",val2);
}
});
I know it's not the most efficient nor pretty code ever written (I'm really new to jQuery and Javascript) - But it does work :) I'd like to apologise to anybody who was kind enough to try to decipher my appalling explanations :/
Note that I also set the Child Div's positioning type to absolute, then Div1 as left: 0; and Div3 as right: 0;
Here is a simple piece of code, resulting in blue span element overflowing out of yellow and black box.
I know, I can use overflow property to hide/scroll it, but I rather need to resize the #inner and #outer containers to cover it (so that scrollbar would rather be on whole page instead of in the containing div). Is there any way?
The content ( = width) of "blue span" is dynamicly generated from application?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<style type="text/css">
#outer {background: black; width: 300px; margin: 10px auto; padding: 20px; }
#inner {background: yellow; min-width: 200px; height: 200px; }
#inner span { background: blue; display: block; width: 400px; }
</style>
<div id="outer">
<div id="inner">
<span> </span>
</div>
</div>
</html>
If you want the two outer boxes to resize dynamically based on the content thats inserted in the span, you will have to reconsider your approach. All boxes that scale dynamically cannot have a width defined, so they cannot be centred using the margin: auto. However, it is possible to achieve the same effect by wrapping the whole thing into another box that covers the full width of the page, text-align centring that box and then making the outer box displayed inline-block. This is the code that works. Now you can add a min-width to the content box if you want and it will scale nicely. Heres some code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<style type="text/css">
#wrap {
width: 100%;
text-align: center;
}
#outer {
display: inline-block;
background: black;
margin: 10px 0;
padding: 20px;
}
#inner {
background: yellow;
height: 200px;
}
#inner span {
background: blue;
display: block;
}
</style>
<div id="wrap">
<div id="outer">
<div id="inner">
<span> </span>
</div>
</div>
</div>
</html>
I think so you can add % units for your divisions to make it as perfect
Here is the CSS
#outer {background: black; width: 300px; margin: 10px auto; padding: 20px; }
#inner {background: yellow; min-width: 200px; height: 200px; }
#inner span { background: blue; display: block; }
Here is the fiddle
http://jsfiddle.net/mohamedmusthafac/n6CEx/
I think so this is what you are expecting for??
<html>
<head>
<style type="text/css">
.parent
{
width: auto;
height: auto;
min-width: 600px;
min-height: 600px;
border: 1px dashed #f00;
padding: 5px;
overflow: auto;
position: absolute;
}
.child
{
width : 100px;
height: 500px;
border: 1px solid #0f0;
float: left;
position: relative;
}
.second_child
{
width : 1800px;
height: 100px;
border: 1px solid black;
float: left;
position:relative;
}
</script>
</style>
</head>
<body style="overflow:auto">
<div class="parent">
<div class="child">
</div>
<div class="second_child">
</div>
</div>
</body>
</html>
I'm trying to put two box in a bigger box. I got it next to each other and it works fine now if I expand the second box width to larger then the width of the window.
Example your screen is 1024x720 the width of the second box is 1800px the second box repositions underneath the first box. I'm just curious why it does that and not put a scroll bar and keep the position of the objects.
Am I positioning it wrong, or am I thinking about this in a wrong manner. I'm almost to tempted to try this with a table as a layout but that seems so counter intuitive to me.
That's the essence of floating DOM elements. They don't force anything. If you want them to stay side by side, you need to give the container a width to support the contents (> 1904px).
I'm just curious why it does that and not put a scroll bar and keep
the position of the objects.
You can set .parent to overflow: scroll; to force this.