Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
What is the right approach to make a 4by4 grid(4 rows and 4 columns) using CSS
I have tried it using column-count but could get the complete look of a grid, borders do not stretch to the elements correctly.
Do we have any other approach. If so please help
Following is the code
#container {
width: 300px;
column-count: 4;
background: green;
border: 1px solid;
column-rule: 1px solid;
}
.box {
color: blue;
border-bottom: 1px solid;
}
.box .contents {
visibility: hidden;
width: 100px;
}
<div id="container">
<div class="box">c-1
<p class="contents"></p>
</div>
<div class="box">c-2
<p class="contents"></p>
</div>
<div class="box">c-3
<p class="contents"></p>
</div>
<div class="box">c-4
<p class="contents"></p>
</div>
<div class="box">c-5
<p class="contents"></p>
</div>
<div class="box">c-6
<p class="contents"></p>
</div>
<div class="box">c-7
<p class="contents"></p>
</div>
<div class="box">c-8
<p class="contents"></p>
</div>
<div class="box">c-9
<p class="contents"></p>
</div>
<div class="box">c-10
<p class="contents"></p>
</div>
<div class="box">c-11
<p class="contents"></p>
</div>
<div class="box">c-12
<p class="contents"></p>
</div>
<div class="box">c-13
<p class="contents"></p>
</div>
<div class="box">c-14
<p class="contents"></p>
</div>
<div class="box">c-15
<p class="contents"></p>
</div>
<div class="box">c-16
<p class="contents"></p>
</div>
</div>
Thanks
That wouldn't work, no. Look at flex-box or float-right for a grid-type arrangement of div elements. Flexbox is especially powerful, really just need 2-3 lines of CSS to accomplish this:
* { box-sizing: border-box; }
#container { width: 100%; display: flex; flex-direction: row; flex-wrap: wrap; background: green; }
#container > div { width: 25%; height: 25vw; border: white 1px solid; }
What's happening:
box-sizing - depending on what browser you're on, the 1px border will add to the overall width and break the grid (example: 25% of 100px box is 25px, but if your box sizing is off, the border can cause the box to "bloat" to 27px. If each box is 27px, one of the boxes is knocked down to the next row bc there's no space left on the row above it).
By setting it to border-box, it means we're including the border when specifying the DOM's width.
width and height:
25% works for width but not height, so we specify the height with the vw measurement. Be careful with this unit, it's not supported by current version -1 (thanks IE).
flex-everything
Neat way to approach modern CSS layout. There are a lot of bells and whistles, but generally speaking I think the rules I used above are pretty self-explanatory. I'm happy to provide any clarification in the comments.
https://jsfiddle.net/z_herring/cg71okst/
Related
I've seen fixes for individual parts of this problem but not one for a collective solution. I can solve everything without resorting to javascript formatting except for margins from elements being carried over to the top of the next column (I can't understand why it hasn't been fixed but it appears to be a bug in css3 for some time that's impeding compositing layouts 1, 2)
I've a responsive div container broken into three columns (though this can change depending on the width of the page, per responsive layout), containg divs with a varying number of nested images of varying aspect ratios that each have a margin-bottom property. The above problem is very apparent so I'm looking for a solution to this.
Typically the suggestion involves the use of a column-break-inside: avoid; property alongside switching my margin-bottom to padding-bottom. This hack has seen some success with others and this is where I point you to the subject of my question. I cannot implement this as I'm using a seperate hack to prevent reflow of images that are lazy loaded (using the lazy sizes plugin*) into the columns (the padding-bottom as a ratio hack, 3).
So if I use padding-bottom to ensure that my column elements align without orphaned margins, I lose the ability to correct the reflow from lazy loading the elements into the columns. I can't use fixed sized elements as the column layout is responsive and the elements shrink and enlarge dynamically with the column size.
Is there anybody who has succeeded in solving both issues simultaneously without javascript formatting?
I'm keen to stick to this particular lazy loading plugin for reasons outside of the scope of this problem.
HTML Code:
<div id='columncontainer'>
<div class='imagecontainer' style='padding-bottom:reflowPaddingAmountFromPHPvar;'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
</div>
CSS Code:
#myContent {
position: relative;
width: 100%;
column-count: 3;
column-gap: 20px;
column-break-inside: avoid;
-moz-column-break-inside:avoid;
-webkit-column-break-inside:avoid;
}
.imagecontainer {
position: relative;
margin-bottom: 20px;
img {
position: absolute;
top: 0;
left: 0;
height: auto;
width: 100%;
}
}
Example jsFiddle:
https://jsfiddle.net/g0yjd9ov/1/
The elements should align at the top of each column but, instead, the margin-bttom on the element (imagecontainer) at the bottom of the first or second column is being carried over to the second or third column and orphaned, giving the impression of the next element having a margin-top value and breaking the top alignment. This serves no benefit to any situation that a deliberate margin-top value couldn't recreate. I've randomised the heights of the elements just for this example, so occasionally the problem won't show (emphasising how much of a nuisance it is. It's hard to deliberately show). Just refresh if it doesn't, as it occurs quite frequently.
This can be solved using an extra container that has padding on it. The container for the image (.imagecontainer) should contain only the image, as that is what its aspect ratio is set up for. The space between a block and the next block in the column can be achieved by setting a padding on that block. The block then gets the styling that prevents column breaks from occurring.
I have created a demo that builds upon the example code in the question, but also includes some things that are only described in the question text. This because I wanted to make sure that everything works the way I think it should (let me know if I misinterpreted the question).
In particular, I added the lazy sizes plugin and let it load some placeholder images. I also added some styling and added blocks that contain more than just a single image. For the rules that prevent breaks inside an element, I used some slightly different ones, as per this answer. Finally, I positioned the .imagetextcontainer as discussed in the question comments.
The demo can be found on JSFiddle. I also include it as a code snippet here.
#columncontainer {
width: 100%;
column-count: 3;
column-gap: 10px;
}
.block-wrap {
width: 100%;
padding-bottom: 10px;
/* prevent column breaks in item
* https://stackoverflow.com/a/7785711/962603 */
-webkit-column-break-inside: avoid; /* Chrome, Safari */
page-break-inside: avoid; /* Theoretically FF 20+ */
break-inside: avoid-column; /* IE 11 */
display:table; /* Actually FF 20+ */
}
.block {
width: 100%;
background-color: #ffff7f;
}
.block > p {
margin: 0;
padding: 10px;
}
.imagecontainer {
position: relative;
width: 100%;
height: 0;
background-color: #a00;
}
.imagecontainer > img {
width: 100%;
}
.imagetextcontainer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<script src="https://afarkas.github.io/lazysizes/lazysizes.min.js"></script>
<div id='columncontainer'>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
<p>Some text. Followed by another figure.</p>
<div class='imagecontainer' style='padding-bottom: 100%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x100/a00/fff 100w,
https://placehold.it/200x200/050/fff 200w,
https://placehold.it/400x400/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
<p>Some text. No figure here.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<p>Only text here.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 100%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x100/a00/fff 100w,
https://placehold.it/200x200/050/fff 200w,
https://placehold.it/400x400/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<p>Only text here.</p>
<p>Tow lines now.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 200%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x200/a00/fff 100w,
https://placehold.it/200x400/050/fff 200w,
https://placehold.it/400x800/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
</div>
After a lot of back and forth I came up with an answer that fixes the problem and maintains the original's CSS properties. There seems to have been two problems causing this.
1 - margins were translating into the next column (but the element was staying into its own column)
2 - height was confined (was a problem in the solution)
solution: since the entire element stays in its own column but the margin is technically not part of the element (it can be tested using outline)
this problem can be solved by placing .imagecontainer into another div which has padding instead of margin. (so then its considered one object so the margin problem is avoided)
you also would need to move column-break-inside to the parent element so it registers without the margin.
a live version can be found at: https://jsfiddle.net/36pqdkd3/6/
Here is a solution using flex-boxes
HTML
<div id='columncontainer'>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer' style=''>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
</div>
CSS
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#columncontainer {
position: relative;
width: 100%;
display: flex;
height: 40%;
/* use this if you want containter wrapping
flex-wrap: wrap; */
/* use this if you want container scrolling
overflow: auto; */
/* use this if you want container scrolling
justify-content: center; */
}
.imagecontainer {
min-width: 250px;
position: relative;
background-color: red;
overflow: hidden;
height: 100%;
margin: 5px;
z-index: 1;
}
example in jsfiddle
Here are some recommendations based on your question.
I would also recommend learning more about flex-boxes, that is very equipped to handle these kinds of situations.
by default the html and body elements default size is width 100% and no height.
here is a reference I use on flex-boxes
addressing aspect ratio
you can handle aspect ratio using px and vw/vh (measurements of DOM width and height). try playing around with min/max/width to find the perfect amount.
(1:2 aspect ratio)
element {
min-width: 10vw;
min-height: 20vh;
width: 50px;
height: 100px;
}
css size units
in my version you can edit ".imagecontainer".
I'm pretty new to HTML and CSS so perhaps this is a crazy easy question to answer.
The question is:
How to do this using only divs and css?
I don't want to use <table> <tr> <th> <td>....
Here's a basic setup of what you're asking using the flexbox property.
The CSS3 Flexible Box, or flexbox, is a layout mode providing for the
arrangement of elements on a page such that the elements behave
predictably when the page layout must accommodate different screen
sizes and different display devices. For many applications, the
flexible box model provides an improvement over the block model in
that it does not use floats, nor do the flex container's margins
collapse with the margins of its contents.
Read more about it at MDN and experiment with it so you feel comfortable using it. The setup might not be pixel perfect, but it gives you a good start for the desired layout. Trial and error, that's the best way to learn.
div {
box-sizing: border-box;
border: 1px solid black;
min-height: 20px;
}
.container {
display: flex;
flex-flow: row-wrap;
width: 100%;
}
.column {
flex: 1 1 100%;
}
.middle {
flex-basis: 200%;
}
.middle-top,
.right-top,
.right-bottom {
display: flex;
flex-flow: row wrap;
width: 100%;
}
.language,
.search,
.login,
.signup,
.some-text,
.avatar {
flex: 1 1 50%;
}
<div class="container">
<div class="column left">
<div class="social">
Social icons
</div>
<div class="logo">
Logo
</div>
</div>
<div class="column middle">
<div class="middle-top">
<div class="language">
Language
</div>
<div class="search">
Search
</div>
</div>
<div class="slogan">
Slogan
</div>
<div class="menu">
Menu
</div>
</div>
<div class="column right">
<div class="right-top">
<div class="login">
Login
</div>
<div class="signup">
Signup
</div>
</div>
<div class="right-middle">
Welcome guest
</div>
<div class="right-bottom">
<div class="some-text">
<div class="something">
Some text
</div>
<div class="something">
Some text
</div>
</div>
<div class="avatar">
Avatar
</div>
</div>
</div>
</div>
In my html I get 'response' from controller. Number of lines in the response varies (max is 3).
What is the best way to 'reserve' 3 lines on my html page so the next div with 'SOMETHING' paragraph is not scrolled down by 'response' ?
<div class="row">
<p ng-bind-html="response"></p>
</div>
<div class="row">
<p>SOMETHING</p>
</div>
Using CSS, fix the height occupied by your 3 rows and use overflow to scroll within that fixed height div.
CSS Overflow might help you.
.row-fixed-height {
height: 150px;
overflow: scroll;
}
and in HTML:
<div class="row-fixed-height">
<p ng-bind-html="response"></p></div>
Since the height of the lines varies based on font and font size, I would use line breaks to "reserve" the three lines. If you were to use for instance a fixed height on the div or p, it might jump around on a different browser that uses a different font.
Live Demo:
#response {
background: red;
}
<div class="row">
<p id="response" ng-bind-html="response">
<br />
<br />
<br />
</p>
</div>
<div class="row">
<p>SOMETHING</p>
</div>
JSFiddle Version: https://jsfiddle.net/rspyho74/
As oori pointed you, this is is about CSS, not Angular. The easiest way to fix the height to 3 lines is using the em unit:
.row{
margin: 10px;
padding: 5px;
border: 1px solid #000;
border-radius: 5px;
}
p{
float: left;
margin: 0 5px;
padding: 5px;
border: 1px solid #000;
height: 3em;
}
<div class="row">
<p ng-bind-html="response"></p>
<p ng-bind-html="response">Line 1</p>
<p ng-bind-html="response">Line 1<br>Line 2</p>
<p ng-bind-html="response">Line 1<br>Line 2<br>Line 3</p>
<div style='clear: both;'></div>
</div>
<div class="row">
<p>SOMETHING</p>
<div style='clear: both;'></div>
</div>
As you can see, the paragraph keeps its height no matter how many lines there are. If you remove the height property you can see the difference.
I'm struggling with getting identical behaviour for a flexbox layout in different browsers (nevermind browsers that don't support flexbox).
Here's the markup:
<!-- nested version -->
<div class="flex-container"> <!-- display: flex -->
<div>
<div class="flex-container inner"> <!-- display: flex -->
<div class="auto-width">
auto take up needed space
</div>
<div class="flex-width"> <!-- flex: 1 -->
flex take up remaining space
</div>
</div>
</div>
</div>
My problem is that IE11 behaves differently to Firefox and Chrome. I would expect that the width of the nested flexbox flex-container.inner will be unrestricted, since nowwhere do I set any width.
Here is a JSBin to illustrate the problem: http://jsbin.com/pabesaci/5. Example 3 is the problematic one which renders differently in IE.
Rendering in IE
Rendering in Chrome (FF is similar)
Is this a bug in IE?
Can you suggest other ways to achieve this layout?
<p>My example:</p>
<div style="float:left; display:block; width: auto; border: solid 2px red; padding: 2px;">
<div>
<div style="float:left; display: block; border: solid 2px yellow; padding:2px;">
<div style="float:left; display: block; border: solid 2px green;">
auto take up needed space
</div>
<div class="" style="float:left; position:relative; display:block; border: solid 2px blue;">
flex take up remaining space
</div>
</div>
</div>
</div>
I am currently making a website for a college task and I am really confused on why the div I am trying to create is not appearing.
It doesn't seem to work since I added the code for the three boxes, they are meant to be the same width as the three boxes.
JsFiddle
<div id="wrapper">
<div id="top">
<div class="logo"> </div>
</div>
<div id="menu">
<div class="button"> Home </div>
<div class="button"> Destinations </div>
<div class="button"> Make A Booking </div>
<div class="button"> Things To Do </div>
<div class="button"> Contact Us </div>
</div>
<div id="box">
content here
</div>
<div id="threeBoxContainer">
<div id="deal_one"></div>
<div id="deal_two"></div>
<div id="deal_three"></div>
</div>
</div>
You just need to add box-sizing property
#deal_one {
/*Other Style */
box-sizing:border-box;
}
#deal_one {
/*Other Style */
box-sizing:border-box;
}
#deal_three {
/*Other Style */
box-sizing:border-box;
}
Reference
Fiddle Demo
You Border-Width in each Box counts to the width.
Look at the Box-Model: http://www.w3schools.com/css/css_boxmodel.asp
Given what you said in the comments, a possible answer:
HTML at the bottom:
<div id="threeBoxContainer">
<div id="deal_one"></div>
<div id="deal_two"></div>
<div id="deal_three"></div>
</div>
<div id="bigbox"></div>
CSS:
#bigbox {
width: 98%;
height: 300px;
background-color:rgba(0, 95, 160, 1);
border: solid 2px black;
margin-top: 5%;
}
It seems to work for me. I can only get a solid line like you referred to if i leave the height out.
Its because css width only represents the content width. Total width is the combination of padding, margin and border.
Total Width=ContentWidth+Padding+Border+Margin
So giving width to 33% and some margin,padding and border is making it actually greater than 33%. Reduce the width size to achieve the desire results. Around 30 or 31% will be good.