I have a parent div containing an unknown number of smaller divs that are used like large icon-like buttons. If a row of child divs is full, I would like them to have equal margins on each side (ie. centered), but if a row is not full I would like them to be filled in from the left side (but still in columns with the elements above). Is there a way to do this with CSS? Resizing the window should maintain the centering and add/remove columns as necessary. All the child div widths are known.
Here's a crappy image of the behavior I'm trying for:
Okay I figured out a solution for this that both allows for equal margins and ALSO aligns divs left in the last row. The caveat is that it uses hidden elements, so the container is taller than the visible elements it contains.
Also it adds a bunch of extra markup to your code. If I thought of any other way to do this, I would do it differently. Sorry.
JSFiddle: https://jsfiddle.net/88qadmo3/2/
#container > div {
margin: 10px;
width: 100px;
height: 100px;
}
.floatleft {
background-color: red;
}
.invis {
visibility: hidden;
}
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
background-color: #DDDDDD;
}
.clearfix {
clear: both;
}
<div id="outer">
<div id="container">
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
</div>
</div>
You can do this by wrapping each of the child elements in an element and using CSS media queries to change the size of the wrappers. Then, just use % width on the wrappers based on what you want the column sizes to be.
When you run the example, shrink it to <400px so you can see it move from 6 columns to 3 (you'll need to run the code snippet on a full-page to see this).
.parent {
border: 2px solid red;
}
.child {
width: 100px;
display: block;
margin: 0 auto;
border: 1px solid black;
}
.wrapper {
display: inline-block;
text-align: center;
float: left;
width: 16.66%;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.clear {
clear: both;
}
#media (max-width: 800px) {
.wrapper {
width: 20%;
}
}
#media (max-width: 600px) {
.wrapper {
width: 25%;
}
}
#media (max-width: 400px) {
.wrapper {
width: 33.33%;
}
}
<div class="parent">
<div class="wrapper">
<div class="child">1</div>
</div>
<div class="wrapper">
<div class="child">2</div>
</div>
<div class="wrapper">
<div class="child">3</div>
</div>
<div class="wrapper">
<div class="child">4</div>
</div>
<div class="wrapper">
<div class="child">5</div>
</div>
<div class="wrapper">
<div class="child">6</div>
</div>
<div class="clear"></div>
</div>
Just use float left, and items of the width (the original fiddle):
<div class="container">
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
</div>
.container {
overflow: auto;
}
.item {
width: 50px;
float: left;
margin: 0 10px;
}
Related
I'm aware of CSS Subgrid being able to solve a layout like this, but what I'm looking to achieve is a list of containers with content inside. The content inside the containers is aligned right in the containers, but all the content is aligned (left) to the longest content.
Is this possible with flex? Are there any strategies to achieve this?
I suppose the HTML structure would be something like:
<div class="container">
<div class="content" style="100px"></div>
</div>
<div class="container">
<div class="content" style="300px"></div>
</div>
<div class="container">
<div class="content" style="400px">All other content aligned to this longest content</div>
</div>
<div class="container">
<div class="content" style="200px"></div>
</div>
It is most definitely doable with flex.
What I've done is create 2 columns inside the .container element. Column 2 will be right aligned inside the container, and your .content will be left aligned inside .column2.
All you need to do to adjust the alignment of the content inside the containers, is to play around with the widths of .column1 and .column2 in the snippet below:
* {
font-family: sans-serif;
}
.container {
display: flex;
background: lightgray;
align-items: center;
border-radius: 5px;
margin-bottom: 10px;
padding: 7px;
}
.content {
display: flex;
align-items: center;
padding: 0 10px;
background: #666;
border-radius: 5px;
color: white;
height: 50px;
}
.column1 {
width: 30%;
}
.column2 {
width: 70%;
}
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content" style="width: 100px"></div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="content" style="width: 250px"></div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content">All other content aligned to this longest content</div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content" style="width: 200px"></div>
</div>
</div>
I've simplified my HTML/CSS in a jsfiddle of what I'm trying to achieve without success.
I cannot make the .problem take full width. The content is represented by the blue background while the box itself is red.
I'm trying to make all the scrollable content have full width and a blue background since I guess the background not appearing after the scrollable content is a problem of width.
What I've taken a look so far:
Flexbox not full width
Flexbox: how to get divs to fill up 100% of the container width without wrapping?
Fill 100% width of scrolling flex container
To clarify: giving .problem a fixed width does give me the effect I want but not the solution since the content is dynamic and I cannot know its width.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html,
body {
width: 100%;
height: 100%;
}
.bg {
display: flex;
background-color: gray;
width: 100%;
height: 100%;
}
.usable {
display: flex;
height: 90%;
width: 100%;
background-color: white;
}
.box {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 300px;
display: flex;
align-items: flex-start;
align-content: flex-start;
flex-direction: column;
background-color: red;
}
.top {
display: flex;
height: 20px;
background-color: yellow;
width: 100%;
}
.bottom {
width: 100%;
flex: 0 1 100%;
overflow: auto;
}
.contents {
height: 100%;
display: flex;
flex-direction: column;
}
.forms {
flex: 0 1 100%;
}
.problem {
display: flex;
height: 100%;
background-color: blue;
}
.row {
display: flex;
align-items: center;
}
.cell {
align-self: stretch;
flex: 1 0 100px;
}
<div class="bg">
<div class="usable">
<div class="box">
<div class="top">
Top
</div>
<div class="bottom">
<div class="contents">
<div class="forms">
<div class="problem">
<div class="data">
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 00:21:06</div>
<div class="cell">test1</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test2</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test3</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test4</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test5</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test6</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test7</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test8</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test9</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:43:11</div>
<div class="cell">test10</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The problem is that the container with the blue background is taking the width of the parent and not the content, to solve this you can change its property "display" to "inline-flex".
Then if you change the "flex" property of the .cell class to a "width" property the width you set will count for the parent and it will reach the blue container making it fill all the content.
.problem {
display: inline-flex;
height: 100%;
background-color: blue;
}
.cell {
align-self: stretch;
width: 100px;
}
To allow elements to grow according to content, you can replace 'width' by 'min-width'.
This makes sure your box is a certain size for styling purposes but allows it to grow.
Then you can use 'max-width' to limit the amount it can grow.
So, change 'width: 100%' by 'min-width: 100%'.
You can find more here: https://css-tricks.com/boxes-fill-height-dont-squish/
Given the following CSS:
.row {
padding: 0;
margin: 0;
list-style: none;
display: flex;
justify-content: space-between;
}
.middle {
flex-grow: 1;
margin: 0 1em;
}
And the following HTML:
<div>
<div class="row">
<div>X</div>
<div class="middle">Variable Content</div>
<div>A</div>
</div>
<div class="row">
<div>X</div>
<div class="middle">Content</div>
<div>AB</div>
</div>
<div class="row">
<div>X</div>
<div class="middle">Var Content</div>
<div>ABC</div>
</div>
</div>
This layout which includes rows and three "columns":
"X" The left column contains the same element in every row, so its width is effectively fixed. This column should only use the amount of space necessary for the element.
"Content" The middle column contains variable text. It should occupy the majority of each row.
"ABC" The right column is where I'm having trouble. The content is text and could be 1-5 characters. I want the characters left aligned across the entire "table". Edit: I don't want to declare a fixed width.
Working example: https://codepen.io/anon/pen/bjEKBW
In short: How do I get the "A" in every column to be left aligned down the entire layout? I'm not married to the HTML layout.
What you have here is a table...I'd suggest you use one or CSS-Tables.
.row {
padding: 0;
margin: 0;
list-style: none;
display: table-row;
}
.row div {
display: table-cell;
padding: 0 .25em;
}
.middle {
width: 100%;
}
<div>
<div class="row">
<div>X</div>
<div class="middle">Variable Content</div>
<div>A</div>
</div>
<div class="row">
<div>X</div>
<div class="middle">Content</div>
<div>AB</div>
</div>
<div class="row">
<div>X</div>
<div class="middle">Var Content</div>
<div>ABC</div>
</div>
</div>
Alternatively, you can dispense with the rows and use CSS Grid
.grid {
display: grid;
grid-template-columns: auto 1fr auto;
}
.grid div {
padding: 0 .25em;
}
<div class="grid">
<div>X</div>
<div class="middle">Variable Content</div>
<div>A</div>
<div>X</div>
<div class="middle">Content</div>
<div>AB</div>
<div>X</div>
<div class="middle">Var Content</div>
<div>ABC</div>
</div>
You can give the last column a fixed width, e.g.
.row > div:last-child {
width: 100px;
}
I'm working with a framework developed in-house which depends on a certain structure to our HTML. And one of the tricky things is that each row needs its own container with its own classes and data attributes.
So here's the problem. Without drastically changing the DOM, how can I make the flex box below render essentially like an HTML table would? Or is a table the only way? The solution will have to work in both IE11 and Chrome.
I'm trying to make it look like this...
Column A | Column B | Column C
1 | 2 | 3
section {
display: flex;
flex-wrap: wrap;
}
section .col {
flex: 1 1 auto;
}
section .line-break {
flex-basis: 100%;
width: 0px;
height: 0px;
overflow: hidden;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="line-break"></div>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
header, .row {
display: flex; /* aligns all child elements (flex items) in a row */
}
.col {
flex: 1; /* distributes space on the line equally among items */
}
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
If the content you are going to present is of type tabular data, then a table is the proper way.
HTML 5.1 W3C Recommendation, 1 November 2016, 4.9 Tabular data
Given that you can't, or don't want to, alter the markup, this can be done using CSS Table, and with that easily swap between any display type such as flex, block, etc., or even float, using media query etc.
I also removed the <div class="line-break"></div> element, since you don't need, though if it is rendered by a component or similar, leaving it as is won't cause any problem.
Using CSS Table
section {
display: table;
width: 100%;
}
section > * {
display: table-row;
}
section .col {
display: table-cell;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
If you still need, or have to, use Flexbox, this answer of mine mention the difference between CSS Table and Flexbox on two important features:
Can flexbox handle varying sizes of columns but consistent row height?
Updated, a sample showing some useful Flexbox stuff, with varying width's and span columns.
Using Flexbox
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="row">
<div class="cell">ID </div>
<div class="cell">Nr </div>
<div class="cell">Header 1 </div>
<div class="cell span4-5"> Header 2 </div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
</div>
<div class="row">
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell span3-5">Content</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell span3-4">Content</div>
<div class="cell">Content</div>
</div>
</div>
This code works for me:
* {
box-sizing: border-box;
}
body, html {
height: 100%;
margin: 0;
}
#container {
width: 400px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
background-color: lightgrey;
padding: 10px;
}
.shelf {
flex: 1 1 auto;
width: 100%;
margin-bottom: 10px;
border: 1px solid black;
background-color: lightgreen;
display: flex;
flex-direction: row;
}
.shelf:last-child {
margin-bottom: 0;
}
.labelbox {
flex: 0 0 35%;
}
.valuebox {
flex: 0 0 65%;
}
<div id="container">
<div class="shelf">
<div class="labelbox">Name: </div> <div class="valuebox">Barry Carter</div>
</div>
<div class="shelf">
<div class="labelbox">DOB:</div><div class="valuebox">10/12/1980</div>
</div>
<div class="shelf">
<div class="labelbox">
Description:
</div>
<div class="valuebox">
This content goes on and on and will force the height to expand. And the label box to the left will
"move" with it. There need not be much of a relation other than that their parent div/flex-container is
getting taller as well.
</div>
</div>
<div class="shelf">
<div class="labelbox">Group:</div><div class="valuebox">Advanced</div>
</div>
<div class="shelf">
<div class="labelbox">End Date:</div><div class="valuebox">2020-09-20</div>
</div>
</div>
Use CSS Grid. You can style any table the way you like.
Keep in mind If your table is more than 700 rows, the fram rate will start to drop, no matter what js framework you use. react, angular, vue or vanila JS. the scrolling will get real laggy.
And the maximum you row can use is 1000. More than that the extra row will create bad graphic. But you wont reach 1000 anyway, because at 700th row, the scrolling speed, starts to get bad.
If somehow you need to display more than 1000 rows, you will visualized lib. Every js framework has a lib to do so. Basically, it will render the rows in the view port. The rows that not in the view port will not be rendered. They will only be rendered when user scrolls.
This is year 2021, chances you read this answer in the future, the browsers vendor might probably fix the performance of 1000 rows, they might even extend that limit. So try it out.
I have two side by side divs but can't seem to figure how to make them responsive.
Looking for the right box to fall under the left box at 600px or lower, maintaining all of the other centering that I've done inside the divs.
Each side-by-side div has class .div-seller-resources-left and .div-seller-resources-right, respectively.
I'm using a media screen of 600px already for the height of each text box so I'll use 600 as the breakpoint for this too.
Have attached photos of what it does in the normal size browser, and what it looks like on a smaller screen. As you can tell, the smaller screen just crunches as best it can to fit all of the content on one page.
/* formats the seller-resources page */
.div-header-seller-resources{
font-size:30px;
line-height:32px;
margin-bottom:10px;
}
.div-detail-seller-resources{
font-size:20px;
line-height:22px;
margin-bottom:45px;
}
/*sets the height of the div so each text box is the same size no matter how much text*/
.seller-resources-height{
height: 125px;
}
/*main container of two side by side boxes*/
.div-main-container-seller-resources{
width:100%;
margin-top:30px;
text-align: center;
display: flex;
justify-content: center;
}
/*div under main container, containing both right and left seller resourcs */
.seller-resources-inner{
display: flex;
flex-direction:row;
}
/*margin here centeres all the content within the div*/
.div-seller-resources-left{
width: 300px;
display: flex;
text-align:center;
margin:0px auto;
}
/*margin here centeres all the content within the div*/
.div-seller-resources-right{
width: 350px;
display: flex;
text-align:center;
margin:0px auto;
}
/* sets the text box screens taller at smaller screens so they don't overlap */
#media screen and (max-width: 600px) {
.seller-resources-height{
height:200px;
}
}
#media screen and (max-width: 600px) {
div-seller-resources-left .div-seller-resources-left{
width:100%;
}
}
<div class="div-main-container-seller-resources">
<div class="seller-resources-inner">
<div class="div-seller-resources-left" style="display: inline-block;">
<div class="seller-resources-height">
<div class="div-header-seller-resources">How Yodega Works</div>
<div class="div-detail-seller-resources">Learn about how Yodega works for sellers</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Referrals</div>
<div class="div-detail-seller-resources">Refer another business to reduce your fees</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">How to Sell with Yodega</div>
<div class="div-detail-seller-resources">Learn the best ways to promote your Yodega store</div>
</div>
<div class="clear"></div>
</div>
<div class="div-seller-resources-right" style="display: inline-block;">
<div class="seller-resources-height">
<div class="div-header-seller-resources">Setting Up Your Store</div>
<div class="div-detail-seller-resources">Detailed instructions on how to build your store</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Advanced Shipping & Product Options</div>
<div class="div-detail-seller-resources">Variable Shipping Costs, Add Product Details and More</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Order Management, Seller Dashboard & Payment</div>
<div class="div-detail-seller-resources">Detailed information on how to manage and fill orders and payments</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>
I would suggest to use the flex-wrap property. In this case you can force the elements into a single column. (See MDN Docs)
Just apply flex-wrap: wrap; to the .seller-resources-inner class (See snippet below).
/* formats the seller-resources page */
.div-header-seller-resources {
font-size: 30px;
line-height: 32px;
margin-bottom: 10px;
}
.div-detail-seller-resources {
font-size: 20px;
line-height: 22px;
margin-bottom: 45px;
}
/*sets the height of the div so each text box is the same size no matter how much text*/
.seller-resources-height {
height: 125px;
}
/*main container of two side by side boxes*/
.div-main-container-seller-resources {
width: 100%;
margin-top: 30px;
text-align: center;
display: flex;
justify-content: center;
}
/*div under main container, containing both right and left seller resourcs */
.seller-resources-inner {
display: flex;
flex-direction: row;
}
/*margin here centeres all the content within the div*/
.div-seller-resources-left {
width: 300px;
display: flex;
text-align: center;
margin: 0px auto;
}
/*margin here centeres all the content within the div*/
.div-seller-resources-right {
width: 350px;
display: flex;
text-align: center;
margin: 0px auto;
}
/* sets the text box screens taller at smaller screens so they don't overlap */
#media screen and (max-width: 600px) {
.seller-resources-height {
height: 200px;
}
.seller-resources-inner {
flex-wrap: wrap;
}
}
#media screen and (max-width: 600px) {
div-seller-resources-left .div-seller-resources-left {
width: 100%;
}
}
<div class="div-main-container-seller-resources">
<div class="seller-resources-inner">
<div class="div-seller-resources-left" style="display: inline-block;">
<div class="seller-resources-height">
<div class="div-header-seller-resources">How Yodega Works</div>
<div class="div-detail-seller-resources">Learn about how Yodega works for sellers</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Referrals</div>
<div class="div-detail-seller-resources">Refer another business to reduce your fees</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">How to Sell with Yodega</div>
<div class="div-detail-seller-resources">Learn the best ways to promote your Yodega store</div>
</div>
<div class="clear"></div>
</div>
<div class="div-seller-resources-right" style="display: inline-block;">
<div class="seller-resources-height">
<div class="div-header-seller-resources">Setting Up Your Store</div>
<div class="div-detail-seller-resources">Detailed instructions on how to build your store</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Advanced Shipping & Product Options</div>
<div class="div-detail-seller-resources">Variable Shipping Costs, Add Product Details and More</div>
</div>
<div class="clear"></div>
<div class="seller-resources-height">
<div class="div-header-seller-resources">Order Management, Seller Dashboard & Payment</div>
<div class="div-detail-seller-resources">Detailed information on how to manage and fill orders and payments</div>
</div>
<div class="clear"></div>
</div>
</div>
</div>