I am trying to achieve a layout with multiple elements of different height stacked on mobile screens and some elements forming a sidebar for desktop, roughly looking like this:
My first idea was to achieve it via CSS grid, defining one row with two columns and then assigning the grid-area depending on the class (orange vs gray):
Codepen
.layout {
display: grid;
max-width: 860px;
margin: 0 auto;
gap: 20px;
}
#media(min-width: 860px) {
.layout {
grid-template-areas: 'main sidebar';
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: main;
}
Problem: as multiple sidebar elements now occupy the same grid cell, they overlap instead of just flow on top of each other. I've been trying to wrap my head around alternative solutions for a few days now, but I couldn't find any so far that did not involve reordering the dom with JavaScript. Am I missing the obvious?
EDIT
Flexbox as stated in the answers does not solve this problem (if the position of elements within the list would be known upfront maybe, but this is not the case). Some elements go in the sidebar, some go in the main bar while having a fixed order in the mobile layout.
Use Flexbox, then you can easily do this.
Refer following code,
.layout {
display: flex;
flex-wrap: wrap;
max-width: 860px;
margin: 0 auto;
gap: 20px;
}
set correct order of div (containers) as you need, (the following code is sample one)
<div id="main">
<div style="background-color:coral;" id="myRedDIV"></div>
<div style="background-color:lightblue;" id="myBlueDIV"></div>
<div style="background-color:lightgreen;" id="myGreenDIV"></div>
<div style="background-color:pink;" id="myPinkDIV"></div>
</div>
#main {
width: 100%;
height: 150px;
border: 1px solid #c3c3c3;
display: flex;
flex-wrap: wrap;
}
#main div {
width: 70px;
height: 70px;
}
/* Standard syntax */
div#myRedDIV {order: 1;}
div#myBlueDIV {order: 4;}
div#myGreenDIV {order: 3;}
div#myPinkDIV {order: 2;}
Refer following links for more about Order in Flexbox
Link1 --> About Flexbox Order
Link2 --> About Flexbox Order
Why don't you try with flexbox. you can do it using display:flex, for more about the flex refer below sample.
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
flex-wrap: nowrap;
background-color: DodgerBlue;
}
.flex-container > div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
line-height: 75px;
font-size: 30px;
}
</style>
</head>
<body>
<h1>Flexible Boxes</h1>
<div class="flex-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
<p>Try to resize the browser window.</p>
<p>A container with "flex-wrap: nowrap;" will never wrap its items.</p>
<p><strong>Note:</strong> Flexbox is not supported in Internet Explorer 10 or earlier versions.</p>
</body>
</html>
This might not be the answer to your question! (cause I've changed the grid layout into FlexBox)
In this example I'm changing flex-direction via screen breakouts.
More Information on CSS Flex box Direction
Code:
* {
border: 1px solid coral;
padding: 12px;
margin: 12px;
}
.layout {
display: flex;
flex-direction: column;
align-items: center;
}
.layout>* {
display: flex;
flex-direction: row;
}
.sidebar {
background-color: yellow;
}
.content {
background-color: grey;
}
#media(max-width: 860px) {
.layout {
display: flex;
flex-direction: column;
align-items: center;
}
.layout>* {
display: flex;
flex-direction: column;
}
.sidebar {
background-color: yellow;
}
.content {
background-color: grey;
}
.content {
background-color: green;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="layout">
<div>
<div class="content big">
Here's some text
</div>
<div class="sidebar small">
Sidebar Item
</div>
</div>
<div>
<div class="content big">
More Text
</div>
<div class="sidebar small">
another sidebar Item
</div>
</div>
</div>
</body>
</html>
Related
I am trying to put together a diagram in CSS of a flow chart. I have attached below a picture. Is there a simple way to do this? I've been Googling around quite a bit looking for examples, but I don't know what to call this.
Can you please let me know how to do this? Or if this is something common, what I can Google to find more information.
By using CSS Flex you could achieve something like:
body {font: 16px/1.4 sans-serif;}
.chart-row,
.chart-col {
display: flex;
gap: 1em;
}
.chart-row {
flex-direction: row;
}
.chart-col {
flex-direction: column;
}
.chart-pill,
.chart-rect{
padding: 1em;
text-align: center;
border: 2px solid #999;
}
.chart-pill {
flex: 1;
border-radius: 1em;
border-style: dashed;
}
.chart-rect{
flex: 0;
margin: auto 0;
background: #eee;
}
.chart-line-h {
height: 2px;
min-width: 3em;
background: #999;
margin: auto -1em;
}
<div class="chart-row">
<div class="chart-pill chart-col">
<div class="chart-rect">alpha</div>
</div>
<div class="chart-line-h"></div>
<div class="chart-pill chart-col">
<div class="chart-rect">beta</div>
<div class="chart-rect">gamma</div>
<div class="chart-rect">delta</div>
</div>
<div class="chart-line-h"></div>
<div class="chart-pill chart-col">
<div class="chart-rect">gamma</div>
</div>
</div>
I'll just add an answer because I can't write any comments yet, although I'm not new at CSS...
Yes, you can use Flexbox but I will also add CSS Grid, as the combination of both can give you more flexibility if you're planning on making bigger charts...
Once you get it working, it's pretty easy to use...
Copy and paste this code in your code editor and display it in your browser.
( if you use VSCode you can use the liveServer extension)
Then go to the dev tools inside your browser (Ctrl+Shift+i) and click the icon to select an element (the one on top at the very left hand side).
Then, inside the first div, you will see a label with the word grid, click it and you'll see the grid on your screen.
Finally, you just have to fill the rows and columns with the figures as in one of those old battleship games, or a 2D Cartesian Coordinate System.
Keep in mind that when placing your items on the Grid, it's better to use the lines instead of the areas of the rows and columns, as it's much easier to understand it this way.
So for instance, in this case, connector1 goes from vertical line 9 to vertical line 10, or the first figure fills the space between line 5 and line 9, and so on.
Hope it helps!
By the way, I changed colours as it's easier for the explanation..
HTML :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Document</title>
</head>
<body>
<!-- GRID FLOWCHART -->
<div class="flowchart">
<!-- FIRST FIGURE -->
<div class="set" id="set1">
<div class="box"><p>alpha</p></div>
</div>
<!-- FIRST CONNECTOR -->
<div class="connector" id="connector1"></div>
<!-- SECOND FIGURE -->
<div class="set" id="set2">
<div class="box"><p>beta</p></div>
<div class="box"><p>gamma</p></div>
<div class="box"><p>delta</p></div>
</div>
<!-- SECOND CONNECTOR -->
<div class="connector" id="connector2"></div>
<!-- THIRD FIGURE -->
<div class="set" id="set3">
<div class="box"><p>gamma</p></div>
</div>
</div>
</body>
</html>
CSS :
body {
width: 100vw;
height: 100vh;
background-color: #d3d3d3;
}
/* ****** GENERIC SHAPES : ********** */
.flowchart {
display: grid;
grid-template-columns: repeat(24, 1fr);
grid-template-rows: repeat(12, 1fr);
width: fit-content;
height: fit-content;
grid-gap: 2px;
}
.set {
min-width: 100px;
min-height: 100px;
border: 2px dashed blue;
border-radius: 15px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.box {
width: 80%;
height: 15%;
background-color: rgb(255, 255, 255);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 4%;
padding: 6%;
border: 1px solid black;
/* border-radius: 5px; */
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 0.9em;
}
.connector {
width: 120%;
max-height: 3px;
background-color: black;
transform: translateX(-6%);
}
/* ************* FIGURES : ************* */
#set1 {
grid-column: 5/9;
grid-row: 5/12;
}
#set2 {
grid-column: 10/14;
grid-row: 5/12;
}
#set3 {
grid-column:15/19;
grid-row: 5/12;
}
/* ******** CONNECTORS : *********** */
#connector1 {
grid-column: 9/10;
grid-row: 8/9;
}
#connector2 {
grid-column: 14/15;
grid-row: 8/9;
}
So I am teaching myself HTML and gave myself a little project that involved having a sidebar with a lot of menu items (34). To do this I used a column flexbox inside of a CSS grid. I expected the sidebar to be implemented with a scrollbar, which I did manage to do, but it cuts off the first and last few menu items and I have no idea why. I've looked all over for an explanation for this but, I can't find anything related to this particular issue.
I've tried changing out the elements I use for the menu items (h2, div, p,...) but the problem remains, even using the least space consuming element. I've looked up flexbox properties and still I can't find anything relevant.
I'm wondering now if it is even a good idea to use flexbox inside of a CSS grid. Am I missing something obvious? Is the approach I'm taking advisable?
As I said, I've just started teaching myself and I would really appreciate any feedback from more experienced programmers out there.
Thanks.
An image of the problem with my scrollbar
/* General elements styles. */
body {
margin: 0;
padding: 0;
}
h1,h2 {
text-align: center;
vertical-align: bottom;
/* padding: 3px; */
}
/* Main CSS grid to organise the shape of the webpage. */
.grid {
display: grid;
grid-template-columns: repeat(9,1fr);
grid-template-rows: repeat(9,1fr);
height: 100vh;
width: 100vw;
align-content: center;
justify-content: center;
background-color: black;
}
.grid-item {
border: thin solid black;
border-collapse: collapse;
background-color: white;
}
.grid-item-1 {
grid-column: 1 / -1;
grid-row: 1 / 2;
background-color: green;
}
.grid-item-2 {
grid-column: 1 / -1;
grid-row: 2 / 3;
background-color: red;
}
.grid-item-3 {
grid-column: 1 / 3;
grid-row: 3 / 10;
background-color: goldenrod;
}
.grid-item-5 {
grid-column: 3 / 10;
grid-row: 3 / 10;
}
/* Flexbox for the main menu navigation bar. */
.nav-flexbox {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.nav-flexbox-item {
flex-basis: 200px;
flex-direction: row;
margin: 0px;
border: thin solid black;
min-height: 50px;
flex-grow: 1;
}
/* Flexbox for the subtopic sidebar. */
.sidebar-flexbox {
display: flex;
flex-direction: column;
justify-content: center;
flex-wrap: nowrap;
height: 100%;
overflow-y: auto;
}
.sidebar-flexbox-item {
flex-basis: 15px;
min-width: 130px;
margin: 0px;
border: 3px solid grey;
border-collapse: collapse;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Learning Italian Webpage</title>
<base>
<link rel="stylesheet" href="Test.css">
<meta charset="UTF-8">
<meta name="viewport" content="width:device-width, initial-scale:1.0">
<script></script>
<style></style>
</head>
<body>
<div class="grid">
<div class="grid-item grid-item-1">
<h1>Learning Italian with Deep Learning</h1>
</div>
<div class="grid-item grid-item-2 nav-flexbox">
<h2 class="nav-flexbox-item nav-flexbox-item-1">Grammar Notes</h2>
<h2 class="nav-flexbox-item nav-flexbox-item-2">Vocab Lists</h2>
<h2 class="nav-flexbox-item nav-flexbox-item-3">Verb Conjugations</h2>
</div>
<div class="grid-item grid-item-3 sidebar-flexbox">
<h2 class="sidebar-flexbox-item">Subject Pronouns</h2>
<h2 class="sidebar-flexbox-item">Present Tense</h2>
<h2 class="sidebar-flexbox-item">Negative Sentences</h2>
<h2 class="sidebar-flexbox-item">Conjunctions</h2>
<h2 class="sidebar-flexbox-item">Object Pronouns</h2>
<h2 class="sidebar-flexbox-item">Other Pronouns</h2>
<h2 class="sidebar-flexbox-item">Modal Verbs</h2>
<h2 class="sidebar-flexbox-item">Interrogative Sentences</h2>
<h2 class="sidebar-flexbox-item">Present Perfect Tense</h2>
<h2 class="sidebar-flexbox-item">Future Tense</h2>
<h2 class="sidebar-flexbox-item">Adjectives</h2>
<h2 class="sidebar-flexbox-item">Present Progressive Tense(s)</h2>
<h2 class="sidebar-flexbox-item">Possessives</h2>
<h2 class="sidebar-flexbox-item">Adverbs</h2>
<h2 class="sidebar-flexbox-item">Relative Pronouns</h2>
<h2 class="sidebar-flexbox-item">Imperative Tense</h2>
<h2 class="sidebar-flexbox-item">Reflexive Verbs</h2>
<h2 class="sidebar-flexbox-item">Past Historic Tense</h2>
<h2 class="sidebar-flexbox-item">Imperfect Tense</h2>
<h2 class="sidebar-flexbox-item">Pluperfect Tense</h2>
<h2 class="sidebar-flexbox-item">Conditional Tenses</h2>
<h2 class="sidebar-flexbox-item">Present Subjunctive Tense</h2>
<h2 class="sidebar-flexbox-item">Past Subjunctive Tense</h2>
<h2 class="sidebar-flexbox-item">Imperfect Subjunctive Tense</h2>
<h2 class="sidebar-flexbox-item">Pluperfect Subjunctive Tense</h2>
<h2 class="sidebar-flexbox-item">Future Perfect</h2>
<h2 class="sidebar-flexbox-item">Hypothetical Sentences</h2>
<h2 class="sidebar-flexbox-item">Prepositions</h2>
<h2 class="sidebar-flexbox-item">Cardinal Numbers</h2>
<h2 class="sidebar-flexbox-item">Ordinal Numbers</h2>
<h2 class="sidebar-flexbox-item">Numerical Expressions, Telling Time and Dates</h2>
<h2 class="sidebar-flexbox-item">Altered and Compound Nouns</h2>
<h2 class="sidebar-flexbox-item">Articles</h2>
<h2 class="sidebar-flexbox-item">Miscellaneous Topics</h2>
</div>
<div class="grid-item grid-item-5"><p>Grid Item 5</p></div>
</div>
</body>
</html>
So the way to fix it is not using display: flex; and removing height: 100%;.
Try it and see if it works for you.
.sidebar-flexbox {
overflow-y: scroll;
}
You have given height: 100vh
/* Main CSS grid to organise the shape of the webpage. */
.grid
{
display: grid;
grid-template-columns: repeat(9,1fr);
grid-template-rows: repeat(9,1fr);
height: 100vh;
width: 100vw;
align-content: center;
justify-content: center;
background-color: black;
}
remove height : 100vh from here and test it or you can give height: 100%
My page starts to change zoom and layout gets slightly messed up when I have a hardcoded width on items located in a Flexbox container (make a very narrow Chrome Devtools responsive window). The problem starts when I make my viewing area narrower than the 300px. Unfortunately, you can't see this problem when running this inside an iframe on jsfiddle - it has to be ran "on it's own", my html block needs to be THE top html block.
Here's the jsfiddle for reference still:
https://jsfiddle.net/elijahww/9e1u7ptr/
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#productShowcaseContainer {
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
.contentContainer {
display: flex;
flex: 1;
}
#productShowcaseTitle {
height: 100px;
background-color: antiquewhite;
}
#productShowcaseThumbnailContainer {
flex: 1;
background-color: darkseagreen;
}
</style>
</head>
<body style="margin: 0;">
<div id="productShowcaseContainer">
<div id="productShowcaseTitle"></div>
<div class="contentContainer">
<div id="productShowcaseThumbnailContainer" style="padding: 10px;">
<input style="width:300px;">
</div>
</div>
</div>
</body></html>
I don't know how to make this work.
here is a gif:
This might be happening because you have hard-coded width of input field as 300px and trying to zoom screen width beyond this.
If you really want to have responsive layout then you should be using flex-layout properly and set flex-basis, flex-grow and flex-shrink property of each layout element.
These properties are responsible for handling responsive behaviour of flex-elements.
To Read more about flex layout follow this link Flex tutorial
One option is to give some parent container overflow-x: auto
body {
background-color: #3d5d6a;
}
#container {
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
.main-content-container {
display: flex;
flex: 1;
}
#top-header-container {
padding: 10px;
height: 100px;
background-color: antiquewhite;
/*align-content: stretch;*/
display: flex;
justify-content: stretch;
}
#main-content-inner {
flex: 1;
background-color: darkseagreen;
}
.responsive-table {
overflow-x: auto;
}
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin: 0;">
<div id="container">
<div id="top-header-container">
<div class="responsive-table">
<input style="width:400px;" value="hard coded to 400px">
</div>
</div>
<div class="main-content-container">
<div id="main-content-inner" style="padding: 10px;">
test
</div>
</div>
</div>
</body></html>
Imagine the following layout, where the dots represent the space between the boxes:
[Left box]......[Center box]......[Right box]
When I remove the right box, I like the center box to still be in the center, like so:
[Left box]......[Center box].................
The same goes for if I would remove the left box.
................[Center box].................
Now when the content within the center box gets longer, it will take up as much available space as needed while remaining centered. The left and right box will never shrink and thus when where is no space left the overflow:hidden and text-overflow: ellipsis will come in effect to break the content;
[Left box][Center boxxxxxxxxxxxxx][Right box]
All the above is my ideal situation, but I have no idea how to accomplish this effect. Because when I create a flex structure like so:
.parent {
display : flex; // flex box
justify-content : space-between; // horizontal alignment
align-content : center; // vertical alignment
}
If the left and right box would be exactly the same size, I get the desired effect. However when one of the two is from a different size the centered box is not truly centered anymore.
Is there anyone that can help me?
Update
A justify-self would be nice, this would be ideal:
.leftBox {
justify-self : flex-start;
}
.rightBox {
justify-self : flex-end;
}
If the left and right boxes would be exactly the same size, I get the desired effect. However when one of the two is a different size the centered box is not truly centered anymore. Is there anyone that can help me?
Here's a method using flexbox to center the middle item, regardless of the width of siblings.
Key features:
pure CSS
no absolute positioning
no JS/jQuery
Use nested flex containers and auto margins:
.container {
display: flex;
}
.box {
flex: 1;
display: flex;
justify-content: center;
}
.box:first-child > span { margin-right: auto; }
.box:last-child > span { margin-left: auto; }
/* non-essential */
.box {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
p {
text-align: center;
margin: 5px 0 0 0;
}
<div class="container">
<div class="box"><span>short text</span></div>
<div class="box"><span>centered text</span></div>
<div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>↑<br>true center</p>
Here's how it works:
The top-level div (.container) is a flex container.
Each child div (.box) is now a flex item.
Each .box item is given flex: 1 in order to distribute container space equally (more details).
Now the items are consuming all space in the row and are equal width.
Make each item a (nested) flex container and add justify-content: center.
Now each span element is a centered flex item.
Use flex auto margins to shift the outer spans left and right.
You could also forgo justify-content and use auto margins exclusively.
But justify-content can work here because auto margins always have priority.
8.1. Aligning with auto
margins
Prior to alignment via justify-content and align-self, any
positive free space is distributed to auto margins in that dimension.
Use three flex items in the container
Set flex: 1 to the first and last ones. This makes them grow equally to fill the available space left by the middle one.
Thus, the middle one will tend to be centered.
However, if the first or last item has a wide content, that flex item will also grow due to the new min-width: auto initial value.
Note Chrome doesn't seem to implement this properly. However, you can set min-width to -webkit-max-content or -webkit-min-content and it will work too.
Only in that case the middle element will be pushed out of the center.
.outer-wrapper {
display: flex;
}
.item {
background: lime;
margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
flex: 1;
display: flex;
min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
justify-content: flex-end;
}
.animate {
animation: anim 5s infinite alternate;
}
#keyframes anim {
from { min-width: 0 }
to { min-width: 100vw; }
}
<div class="outer-wrapper">
<div class="left inner-wrapper">
<div class="item animate">Left</div>
</div>
<div class="center inner-wrapper">
<div class="item">Center</div>
</div>
<div class="right inner-wrapper">
<div class="item">Right</div>
</div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>
The key is to use flex-basis. Then the solution is simple as:
.parent {
display: flex;
justify-content: space-between;
}
.left, .right {
flex-grow: 1;
flex-basis: 0;
}
CodePen is available here.
Here's an answer that uses grid instead of flexbox. This solution doesn't require extra grandchild elements in the HTML like the accepted answer does. And it works correctly even when the content on one side gets long enough to overflow into the center, unlike the grid answer from 2019.
The one thing this solution doesn't do is show an ellipsis or hide the extra content in the center box, as described in the question.
section {
display: grid;
grid-template-columns: 1fr auto 1fr;
}
section > *:last-child {
white-space: nowrap;
text-align: right;
}
/* not essential; just for demo purposes */
section {
background-color: #eee;
font-family: helvetica, arial;
font-size: 10pt;
padding: 4px;
}
section > * {
border: 1px solid #bbb;
padding: 2px;
}
<section>
<div>left</div>
<div>center</div>
<div>right side is longer</div>
</section>
<section>
<div>left</div>
<div>center</div>
<div>right side is much, much longer</div>
</section>
<section>
<div>left</div>
<div>center</div>
<div>right side is much, much longer, super long in fact</div>
</section>
Instead of defaulting to using flexbox, using grid solves it in 2 lines of CSS without additional markup inside the top level children.
HTML:
<header class="header">
<div class="left">variable content</div>
<div class="middle">variable content</div>
<div class="right">variable content which happens to be very long</div>
</header>
CSS:
.header {
display: grid;
grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
/* use either */
margin: 0 auto;
/* or */
text-align: center;
}
Flexbox rocks but shouldn't be the answer for everything. In this case grid is clearly the cleanest option.
Even made a codepen for your testing pleasure:
https://codepen.io/anon/pen/mooQOV
You can do this like so:
.bar {
display: flex;
background: #B0BEC5;
}
.l {
width: 50%;
flex-shrink: 1;
display: flex;
}
.l-content {
background: #9C27B0;
}
.m {
flex-shrink: 0;
}
.m-content {
text-align: center;
background: #2196F3;
}
.r {
width: 50%;
flex-shrink: 1;
display: flex;
flex-direction: row-reverse;
}
.r-content {
background: #E91E63;
}
<div class="bar">
<div class="l">
<div class="l-content">This is really long content. More content. So much content.</div>
</div>
<div class="m">
<div class="m-content">This will always be in the center.</div>
</div>
<div class="r">
<div class="r-content">This is short.</div>
</div>
</div>
Here is another way to do it, using display: flex in the parents and childs:
.Layout{
display: flex;
justify-content: center;
}
.Left{
display: flex;
justify-content: flex-start;
width: 100%;
}
.Right{
display: flex;
justify-content: flex-end;
width: 100%;
}
<div class = 'Layout'>
<div class = 'Left'>I'm on the left</div>
<div class = 'Mid'>Centered</div>
<div class = 'Right'>I'm on the right</div>
</div>
A slightly more robust grid solution looks like this:
.container {
overflow: hidden;
border-radius: 2px;
padding: 4px;
background: orange;
display: grid;
grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr);
}
.item > div {
display: inline-block;
padding: 6px;
border-radius: 2px;
background: teal;
}
.item:last-child > div {
float: right;
}
<div class="container">
<div class="item"><div contenteditable>edit the text to test the layout</div></div>
<div class="item"><div contenteditable>just click me and</div></div>
<div class="item"><div contenteditable>edit</div></div>
</div>
And here you can see it in Codepen: https://codepen.io/benshope2234/pen/qBmZJWN
I wanted the exact result shown in the question, I combined answers from gamliela and Erik Martín Jordán and it works best for me.
.parent {
display: flex;
justify-content: space-between;
}
.left, .right {
flex-grow: 1;
flex-basis: 0;
}
.right {
display: flex;
justify-content: flex-end;
}
you can also use this simple way to reach exact center alignment for middle element :
.container {
display: flex;
justify-content: space-between;
}
.container .sibling {
display: flex;
align-items: center;
height: 50px;
background-color: gray;
}
.container .sibling:first-child {
width: 50%;
display: flex;
justify-content: space-between;
}
.container .sibling:last-child {
justify-content: flex-end;
width: 50%;
box-sizing: border-box;
padding-left: 100px; /* .center's width divided by 2 */
}
.container .sibling:last-child .content {
text-align: right;
}
.container .sibling .center {
height: 100%;
width: 200px;
background-color: lightgreen;
transform: translateX(50%);
}
codepen: https://codepen.io/ErAz7/pen/mdeBKLG
Althought I might be late on this one, all those solutions seems complicated and may not work depending on the cases you're facing.
Very simply, just wrap the component you want to center with position : absolute, while letting the other two with justify-content : space-between, like so :
CSS:
.container {
display: flex;
justify-content: space-between;
align-items: center;
background-color: lightgray;
}
.middle {
position: absolute;
margin-left: auto;
margin-right: auto;
/* You should adapt percentages here if you have a background ; else, left: 0 and right: 0 should do the trick */
left: 40%;
right: 40%;
text-align: center;
}
/* non-essential, copied from #Brian Morearty answer */
.element {
border: 1px solid #ccc;
background-color: lightgreen;
}
p {
margin: 5px;
padding: 5px;
}
<div class="container">
<p class="element">First block</p>
<p class="middle element">Middle block</p>
<p class="element">Third THICC blockkkkkkkkk</p>
</div>
Michael Benjamin has a decent answer but there is no reason it can't / shouldn't be simplified further:
.container {
display: flex;
}
.box {
flex: 1;
display: flex;
justify-content: center;
}
.box:first-child { justify-content: left; }
.box:last-child { justify-content: right; }
And html
<div class="container">
<div class="box">short text</div>
<div class="box">centered tex</div>
<div class="box">loooooooooooooooong text</div>
</div>
I've got an issue on my webpage that involves margins popping up next to flexboxes when the site is viewed on mobile. I've distilled the issue down to some pretty simple code.
HTML Code
<html>
<head>
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<!-- When you remove this period, issue goes away -->
.
<div class="smallboxes">
<div class="smallbox1">
</div>
<div class="smallbox2">
</div>
</div>
<div class="bigbox">
</div>
</div>
</body>
</html>
CSS code
.container {
display: flex;
height: 100px;
}
.bigbox {
flex: 2;
background-color: #6e6e6e;
display: flex;
}
.smallboxes {
flex: 1;
display: flex;
flex-direction: column;
}
.smallbox1 {
flex: 2;
background-color: #6e6e6e;
}
.smallbox2 {
flex: 1;
}
When you run the code in Chrome, right-click, click "Inspect", view as IPad Pro in horizontal mode and change the view to 75% or 125%. You'll see a white line between the two boxes. This is showing up on my Note 5 as well. There should be no line between the two grey boxes.
As I mention in the code, when you remove the period, the issue goes away.
Thanks a ton for the help!
P.S. I'm new to SO and can't seem to figure out how insert the "run codepen on this code" button. I'm including a link to the codepen version of this as well.
http://codepen.io/jasonhoward64/pen/XMpYXJ
edit: new answer based on comments of author
I've been playing with your Codepen and the problem is because of the use of "Flex: 1". Flex creates the needed space inside your "container". if you give ".bigBox" flex:2; and ".smallBoxes" flex:1; it will divide ".container" into 3 parts where bigBox will take up 2. When you add an item inside the container without giving it a flex-value, it will try to calculate the needed space.
Try placing the dot inside a span or div (or other element) and give it a flex-value. This will solve your problem.
.container {
display: flex;
height: 100px;
background: red
}
.bigbox {
flex: 5;
background-color: #6e6e6e;
display: flex;
}
.testBox {
background: yellow;
flex: 1;
}
.smallboxes {
flex: 3;
display: flex;
flex-direction: column;
}
.smallbox1 {
flex: 2;
background-color: #6e6e6e;
}
.smallbox2 {
flex: 1
}
<html>
<head>
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<!-- When you remove this period, issue goes away --> <span class="testBox">test</span>
<div class="smallboxes">
<div class="smallbox1">
</div>
<div class="smallbox2">
</div>
</div>
<div class="bigbox">
</div>
</div>
</body>
</html>
You're code works, but when you add margin of 0 to the body, it breaks again. Do you know why?
body {
margin: 0;
}
.container {
display: flex;
height: 100px;
background: red
}
.bigbox {
flex: 5;
background-color: #6e6e6e;
display: flex;
}
.testBox {
background: yellow;
flex: 1;
}
.smallboxes {
flex: 3;
display: flex;
flex-direction: column;
}
.smallbox1 {
flex: 2;
background-color: #6e6e6e;
}
.smallbox2 {
flex: 1
}
<html>
<head>
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<!-- When you remove this period, issue goes away --> <span class="testBox">test</span>
<div class="smallboxes">
<div class="smallbox1">
</div>
<div class="smallbox2">
</div>
</div>
<div class="bigbox">
</div>
</div>
</body>
</html>