Aligning flexbox item next to flex-grow item - html

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;
}

Related

Align matching content in separate containers depending on width of largest content

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>

how can I separate 2 divs equally from left and right?

Im a new in css and html. How can I separate 2 divs equally from left and right?? Here's my html code.
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
you can try this. Learn Bootstrap grid or flexbox that would be easy for these kinds of task.
.container{
width:100%;
display:flex; /* for display it's child div beside each other */
}
.first-div,.second-div{
width:50%; /* for divide container into 2 equal divs */
border: 1px solid black; /* for border around divs */
}
<div class="container">
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
</div>
You have several options and it all depends on your exact use case.
The first option is to set both to 50% of the available width (left and right):
.first-div {
display: inline-block;
width: 50%;
}
.second-div {
display: inline-block;
width: 50%;
}
<div class="first-div">
<h1>About</h1>
</div><div class="second-div">
<h1>Services</h1>
</div>
Another option is to use flex:
.wrapper {
display: flex;
}
.first-div {
flex-grow: 1;
}
.second-div {
flex-grow: 1;
}
<div class="wrapper">
<div class="first-div">
<h1>About</h1>
</div>
<div class="second-div">
<h1>Services</h1>
</div>
</div>
If you're not familiar with flex, flexbox froggy is a great interactive way to learn.
And a final option is to use grid:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
<div class="wrapper">
<div class="first-div">
<h1>About</h1>
</div>
<div class="second-div">
<h1>Services</h1>
</div>
</div>
If you're not familiar with grid, grid garden is a great interactive way to learn.
Sidenote: make sure to also properly close the <h1> tags with a </h1>.
Try this code. Hope it useful for your question.
/* CSS */
.container-box{
width:100%;
display:flex;
}
.first-div,.second-div{
width:50%;
border:1px solid #ddd; //just to look
}
<!-- HTML -->
<div class="container-box">
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
</div>
Check Css FlexBox .
FlexBox Tutorial
<div class="mainContainer" style="
display: flex;
justify-content: space-around;
">
<div class="first" style="
border: 1px solid;
">
<h1>About</h1><h1>
</h1></div>
<div class="second-div">
<h1>Services</h1><h1>
</h1></div>
</div>

Layout a flex box similar to a table?

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.

Set baseline of flexbox elements

Consider this HTML
<div class="container">
<div class="element">
<div class="top">
<div>A</div>
<div>B</div>
</div>
<hr/>
<div class="bottom">
<div>C</div>
</div>
</div>
<div class="element">
<div class="top">
<div>A</div>
</div>
<hr/>
<div class="bottom">
<div>B</div>
<div>C</div>
</div>
</div>
<div class="element">
<div class="top">
<div>A</div>
</div>
<hr/>
<div class="bottom">
<div>B</div>
</div>
</div>
</div>
I want to line the elements up horizontally using flexbox, such that the horizontal rules align. It seems that align-items: baseline would do the right thing – if I could make sure the element divs have their baseline at the horizontal bar.
See this codepen link for something to play around with.
How can I control the baseline of such a block element?
You could use multiple stacked flexboxes to achieve this, however HTML gets more complex, but it looks like the only way to pretend you set the baseline yourself.
Demo : https://jsfiddle.net/Paf_Sebastien/tLk1jajo/
The content over the line is in one flexbox with :
.overline {
align-items: flex-end;
}
The content under the line in another with :
.underline {
align-items: flex-start;
}
I want to line the elements up horizontally using flexbox, such that
the horizontal rules align. It seems that align-items: baseline would
do the right thing
align-items: baseline is not going to help you here, because you want to align different elements with respect to another element (the hr as opposed to aligning same elements based on the text baseline).
If you can work with fixed heights of your .elements, then without changing your markup, you could do a nested flex and equalize your .top and .bottom, like this:
.top, .bottom {
height: 49%;
display: flex; flex-direction: column;
align-items: center;
}
.top > div, .bottom > div { flex: 0 0 auto; }
And then, to align the .top one to the bottom (i.e. close to the hr), you would do a margin-top: auto, like this:
.top > div { margin-top: auto; }
This will also play along nicely with your flex-wrap: wrap. Try changing the width of the fiddle pane, or window size in the examples below.
Complete Example Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
.container {
height: 320px; border: 1px solid #ddd;
display: flex; flex-wrap: wrap;
align-items: center;
}
.element {
flex: 1 1 auto;
height: 120px; width: 200px;
padding: 0.5em;
}
.top, .bottom {
height: 49%;
display: flex; flex-direction: column;
align-items: center;
}
.top > div, .bottom > div { flex: 0 0 auto; }
.top > div { margin-top: auto; }
<div class="container">
<div class="element">
<div class="top">
<div>A</div>
<div>B</div>
</div>
<hr/>
<div class="bottom">
<div>C</div>
</div>
</div>
<div class="element">
<div class="top">
<div>A</div>
</div>
<hr/>
<div class="bottom">
<div>B</div>
<div>C</div>
</div>
</div>
<div class="element">
<div class="top">
<div>A</div>
</div>
<hr/>
<div class="bottom">
<div>B</div>
</div>
</div>
</div>
Fiddle: http://jsfiddle.net/abhitalks/vym76nyn/
Codepen: http://codepen.io/anon/pen/ZbOyzE
.

Center align HTML Elements, while adding new items from left

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;
}