css column alignment for unequal height divs - html

I am trying to recreate alignment of divs with unequal heights.
Here is the JSFiddle link: jsfiddle
As per the example give if only 1 child exists it should be centered, otherwise the children should be side by side in 2 columns. I achieved that using flex but I'm facing an issue that if the height of children is big it is leaving a big space as shown in fiddle with div "weird space above this box"
SCSS code:
body {
background: grey;
}
.container {
max-width: 500px;
ul {
list-style-type: none;
background: white;
padding: 30px;
display: flex;
flex-wrap: wrap;
justify-content: center;
>li {
border: 2px solid black;
width: 42%;
height: fit-content;
padding: 5px;
margin: 10px;
}
}
}
HTML:
<div class="container">
<ul class="parent">
<li>child 1 </li>
</ul>
</div>
<div class="container">
<ul class="parent">
<li>child 1 </li>
<li>child 2 child 2</li>
</ul>
</div>
<div class="container">
<ul class="parent">
<li>child 1 </li>
<li>child 2 child 2</li>
<li>child child child child child child child child v child child child child child child child child child child child child child child </li>
<li>child child</li>
<li>child child</li>
<li>weird space above this box</li>
<li>child child</li>
</ul>
</div>

I think what you are asking for is the two columns to be equal height? Remove height: fit-content; from the > li css block and the heights should grow to be equal.

You can remove height property from child. This will result in both the child taking full height.
height: fit-content;

Related

How to inline+wrap elements and their children in a flex container?

I need to display some elements inline so they wrap when they fill the viewport width. I'd prefer to use flex with - easy and maintainable, gap clearly defined - instead of inline or floats - you need to use margins for the gap, then avoid ugly wraps using negative margin...
Problem is I am not being able to do it when the items to align are nested on different parents. Example of the tags I'd like to align:
div wrapper:
ul list of some related items
li item
li item
span item not in list
span item not in list
I am attaching a demo, where the structgure is repeated 3 times, each time offering less width to showcase how the items wrap. The ul behaves perfectly as an inline element, until it has to wrap, then it behaves as a block element.
div {
border: 1px solid blue; /* for easier debugging */
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 40px; /* just visual separation between the 3 examples */
}
div:nth-of-type(2) {
max-width: 450px; /* stretcher just to show how items wrap */
}
div:nth-of-type(3) {
max-width: 250px; /* stretcher just to show how items wrap */
}
ul {
border: 1px solid green; /* for easier debugging */
display: inline-flex;
flex-wrap: wrap;
gap: 20px;
}
li, span {
border: 1px solid red; /* for easier debugging */
display: inline;
}
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
<!-- structure repeats 3 times -->
<p>This wraps okay</p>
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
<p>The UL pushed next inline elements to a new line :(</p>
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
Use the display: contents property on the ul element, which allows the child elements to be treated as if they were direct children of the parent container.
ul {
display: contents;
}
Can also use display: inline-block on the li and span elements instead of display: inline which allow them to have their own layout. Also you can use white-space: nowrap on the ul to prevent it from breaking to a new line.
li, span {
display: inline-block;
}
ul {
white-space: nowrap;
}
* {
/* just for reset and for remove all margins and paddings */
box-sizing: border-box;
margin: 0;
padding: 0;
}
div {
border: 1px solid blue;
/* for easier debugging */
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 40px;
/* just visual separation between the 3 examples */
}
div:nth-of-type(2) {
max-width: 450px;
/* stretcher just to show how items wrap */
}
div:nth-of-type(3) {
/* max-width: 250px; */
max-width: fit-content;
/* is like 488px, but is resizable*/
/* you wrong, the ul by default doesn't
push to next line any elements,
you have did a static width
of maximum 250px...*/
/* stretcher just to show how items wrap */
}
ul {
border: 1px solid green;
/* for easier debugging */
display: inline-flex;
flex-wrap: wrap;
gap: 20px;
}
li, span {
border: 1px solid red;
/* for easier debugging */
display: inline;
}
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
<!-- structure repeats 3 times -->
<p>This wraps okay</p>
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
<p>The UL pushed next inline elements to a new line :(</p>
<div>
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
<span>Action 1</span>
<span>Action 2</span>
<span>Action 3</span>
</div>
You have did a "static" width on 2nd child of max(250px) and then, they can't wrap anymore beacuse they were already wrapped.

Set space-between between flex list items [duplicate]

This question already has answers here:
How can I align one item right with flexbox?
(5 answers)
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 2 years ago.
I've got a navigation which looks sort like a this one under, and li items inside are flex items. This menu is rendered from the outside, and I'm not able to wrap any of the items inside the dedicated container.
What I'm trying to achieve is to set space-between between the last item and the other ones on the left. I've tried to do it with a margin-left on the last child, but it's not a nicest solution.
Is there a CSS option to "wrap" the last item somehow, so there's always space between that one and the ones on the left?
.container {
max-width: 1000px;
background-color: lightblue;
}
ul {
display: flex;
justify-content: space-between;
}
.last {
background: red;
}
<div class="container">
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="last">Last Item</li>
</ul>
</div>
Using margin-left on the last element is a good solution. However, you can improve your implementation by using the :last-child selector:
ul li:last-child {
margin-left: 10px;
}
Instead of manually assigning the last class to the last child.
EDIT: If you mean you want your last child to be aligned all the way to the right. You can separate them into different lists, and use justify-content: space-between:
.container {
max-width: 1000px;
background-color: lightblue;
display: flex;
justify-content: space-between;
}
ul {
display: flex;
}
ul li {
width: 3rem;
}
.right li {
background-color: red;
}
<div class="container">
<ul class="left">
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<ul class="right">
<li>Item</li>
</ul>
</div>

Making a horizontal list take up full div width, while vertical lists take up minimum width and pad the rest

I have an element with a pre-determined width, and within that element I have 1 or more lists. Each list will have a class defining whether it is horizontal or vertical.
The horizontal list needs to span the full width of the div, but center the list items. When try to make the list items equally share the space given to them rather than just centering, I get no results - I don't have to worry about horizontal overflow, since I can just make a second horizontal list if I need to.
The same thing is true for when I try to do this with the vertical lists.
.c {
display: block;
width: 90%;
background: orange;
padding: 1% 5%;
text-align: center;
}
ol {
list-style-type: none;
padding: 0;
}
.h {
display: block;
background: blue;
}
.h li {
display: inline-block;
background: green;
}
.v {
display: inline-block;
background: red;
}
.v li {
background: violet;
}
<div class="c">
<ol class="h">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
<ol class="v">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
<ol class="v">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
</div>
And I want to end up with this:
How do I get the horizontal items to self-pad, as well as the vertical lists? I'm looking for results without the use of tables, display: table (etc), and flex, if possible. It doesn't matter if extra space is filled in with padding or margin to me.
This div container .c has 90% width.
So the properties are being inherited by the other classes it seems.
You also have the issue of the yellow background not covering the other classes.
The changes I made were creating a new class to wrap around everything to make sure it all has the yellow background and I also wrapped your .c div around the other 2 classes instead and changed the .h class to display inline-block, this means you can set the height and width of the element while keeping it inline, I set the width to 100% and aligned the text to centre.
.d {
background: orange;
}
.c {
display: block;
width: 90%;
padding: 1% 5%;
text-align: center;
}
ol {
list-style-type: none;
padding: 0;
}
.h {
text-align: center;
display: inline-block;
width: 100%;
background: blue;
}
.h li {
display: inline-block;
background: green;
}
.v {
display: inline-block;
background: red;
}
.v li {
background: violet;
}
<div class="d">
<ol class="h">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
<div class="c">
<ol class="v">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
<ol class="v">
<li>Item</li>
<li>Line</li>
<li>List</li>
</ol>
</div>
</div>
You have 4 options;
Make CSS rules for all the possible amounts of horizontal list elements
Use tables
Use JavaScript
Use flex
I can write examples for all those options, or just the option(s) you'd like.

Create a two column layout that fits to content with Flexbox

I have a two column layout. Column 1 is a heading. Column 2 is a list.
I want the columns to fit to content. (e.g. Column 1 should be as wide as it's contents)
I also want the list to be horizontal.
I want to use Flexbox, so I can change items in the list and have the layout adapt accordingly.
E.g. So it looks like this:
How can I do this?
Here is my code (Codepen is here):
<div class="wrapper">
<nav class="topics">
<span class="unit unit-header">Topics: </span>
<ul id="list" class="list unit">
<li>All</li>
<li>Topic 1</li>
<li>Topic 2</li>
<li>Topic 3</li>
<li>Topic 4</li>
<li>Topic 5</li>
<li>Topic 5</li>
</ul>
</nav>
</div>
.wrapper {
width: 960px;
margin: auto;
padding-top:20px;
}
.topics {
display: flex;
}
.unit {
flex: 1 auto;
}
.list {
display:flex;
}
.list li {
flex: 1 auto;
}
If I add the following code, it works:
.unit-header {
display: table;
padding-right: 5%;
}
However, mixing table with flex-box seems a bit hacky to me. Is there a better way?
Have you tried using this instead?
.unit-header {
flex: 0 1 auto;
}
The above shorthand property means:
flex-grow: 0
flex-shrink: 1
flex-basis: auto

Make a list item maintain fixed position on resize

Suppose there's an unordered list inside a resizable div container, and that list is laid out horizontally and aligned to the right.
In that list one of the items is chosen as "special", say is assigned id="pinned".
Is it possible by means of CSS only to make the #pinned item maintain its position relative to a containing div while that div is resized, so that other list items may change their position (float) around the #pinned item?
Here's an image of what I mean:
Yes, you can do that. This code will only work if the pinned list item is the first in the list.
HTML:
<ul>
<li id="pinned">item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
CSS:
ul {
background: lightyellow;
padding: 10px;
text-align: right;
}
li {
padding: 10px 50px;
background: lightblue;
display: inline-block;
margin: 10px;
}
#pinned {
float: right;
background: lightgreen;
margin-left: 14px;
}
DEMO