How to Center a list of inline-block items, while aligning the content of the list to the Left? - css

I have a list of inline-block elements inside a parent element. I wont to center the parent element while keeping the child elements aligned to the left.
<body>
<style>
/* the width of the container is dynamic by the width of the window */
.container {
height: 600px;
text-align: center;
border: 1px solid red;
overflow-y: auto;
}
/* i don't know the width of the list element, it's only for centering */
.list {
text-align: left;
}
/* the width of the item is const - always 200px */
.item {
display: inline-block;
width: 200px;
height: 200px;
margin: 10px;
background: gray;
}
</style>
<div class="container">
<div class="list">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
</div>
</body>
As you can see in the attached example, the list element isn't centered.
If I remove the align: left style then the list element will be centered but then the item elements will be centered as well (I want them to be aligned to the left)
This what I'm trying to achieve:

Some thing like this just give text-align: left; to item and remove text-align: center; from list
<body>
<style>
.container {
width: 600px;
height: 600px;
text-align: center;
border: 1px solid red;
overflow-y: auto;
}
.item {
display: inline-block;
width: 200px;
height: 200px;
margin: 10px;
background: gray;
text-align: left;
}
</style>
<div class="container">
<div class="list">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</div>
</body>

make all items fit the width of the list either by putting a fixed width to list or edit the width of item to have less than 50% of list, .item{width: 46%;} worked well
.container {
width: 600px;
height: 900px;
border: 1px solid red;
overflow-y: auto;
}
.list {
border: 1px solid #bbb;
width: 445px;
margin: 0px auto;
}
.item {
text-align: left;
display: inline-block;
width: 200px;
height: 200px;
margin: 10px;
background: gray;
}
<body>
<div class="container">
<div class="list">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</div>
</body>

What are you actually trying to achieve?
Now you have .container and .list that are both 600px wide, so you don't see if list element is aligned to left or center.
First, you should have different widths for .list and .container. Then your list should be an inline-block element for it to react to text-align: center.
I made a codepen for you to make this more clear: https://codepen.io/leo-melin/pen/MWYbLLa
.container {
width: 800px;
height: 600px;
text-align: center;
border: 1px solid red;
overflow-y: auto;
}
.list {
display: inline-block;
width: 500px;
border: solid 1px #000; /* Added border to make it visual */
text-align: left;
}
.item {
display: inline-block;
width: 200px;
height: 200px;
margin: 10px;
background: gray;
}
UPDATE 1
If I now understand you correctly, you have n-elements per row that are all 200px wide and you want to center them in container if there's not enough space to fit another 200px element. You want the last item to be aligned to left inside the container.
As in this another stackoverflow answer: https://stackoverflow.com/a/40936683/2061685 you probably need to utilize flexbox for that behaviour to work.
So something like this would do:
<div class="container">
<div class="list">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
<div class="item phantom"></div>
</div>
</div>
.container {
width: 100%;
height: 600px;
border: 1px solid red;
overflow-y: auto;
text-align: center;
}
.list {
display: inline-flex;
flex-wrap: wrap;
justify-content: center;
text-align: left;
}
.list:after {
content: '';
flex: auto;
}
.item {
display: inline-block;
width: 200px;
height: 200px;
margin: 10px;
background: gray;
}
.item.phantom {
visibility: hidden;
height: 0;
}
Working codepen: https://codepen.io/leo-melin/pen/gObgLrX
As you can see, you need to add those phantom items to make the last element stay on the left. On very wide screen with just a few items, you need to control the amount of phantom elements. Use mediaqueries or define an algorithm while rendering the items to make sure it works in all cases.
Hope this helps now for you to figure out a solution.

Related

How to break multiple divs in next line if can't fit [duplicate]

This question already has answers here:
Why are flex items not wrapping?
(2 answers)
Closed 10 months ago.
I want to put multiple divs in same row and if they cant fit to break to next line.I want this enter image description here instead of this enter image description here
.cardContainer {
display: flex;
}
.card {
min-width: 185.17px;
height: 88px;
border-radius: 8px;
background: red;
margin-right: 8px;
display: block;
}
<div className="cardContainer">
<div className="card">A</div>
<div className="card">A</div>
<div className="card">A</div>
<div className="card">A</div>
<div className="card">A</div>
<div className="card">A</div>
<div className="card">A</div>
</div>
CSS Flexbox would be your friend:
.cardContainer {
display: flex;
gap: 10px;
}
.card {
background-color: red;
color: white;
width:20%;
border-radius: 8px;
padding: 10px;
height: 100px;
}
<div class="cardContainer">
<div class="card">A</div>
<div class="card">A</div>
<div class="card">A</div>
<div class="card">A</div>
<div class="card">A</div>
<div class="card">A</div>
<div class="card">A</div>
</div>
.container {
display: flex;
flex-wrap: no-wrap;
gap: 10px 10px;
}
.item {
width: 20%;
height: 50px;
background-color: red;
}
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
</div>

Flexbox item does not shrink when only one item [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 3 years ago.
In flexbox, if you set flex-flow: column nowrap and the elements inside have non-zero value of flex shrink, they should shrink down to all fit inside the flex container.
I have found that if you have only one item in this container and it has content bigger than the flex-container then it will not shrink down. But if other elements are included in the container (if it is not the only item) then it will shrink down.
Best visualized in this CodePen.
Here is the same code from the CodePen.
.container {
padding: 10px;
height: 100px;
width: 100px;
background: red;
margin: 5px 20px;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.item {
width: 80px;
height: 40px;
background: blue;
margin: 5px;
/* same as
flex: 1 1 40px;
*/
}
.super.item {
height: 200px;
}
.item div {
width: 10px;
height: 150px;
background: black;
}
body {
margin: 0;
display: flex;
}
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'>
</div>
</div>
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'>
<div></div>
</div>
</div>
<div class='container'>
<div class='item super'>
</div>
</div>
<div class='container'>
<div class='item super'>
<div></div>
</div>
</div>
Is there an explanation on why that last div does not shrink to fit the flex container?
What about making the height of those contents inherit their parent's one?
.super.item {
height: inherit;
}
.item div {
width: 10px;
height: inherit;
background: black;
}
Snippet below, is that what you're trying to achieve? :
.container {
padding: 10px;
height: 100px;
width: 100px;
background: red;
margin: 5px 20px;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.item {
width: 80px;
height: 40px;
background: blue;
margin: 5px;
/* same as
flex: 1 1 40px;
*/
}
.super.item {
height: inherit;
}
.item div {
width: 10px;
height: inherit;
background: black;
}
body {
margin: 0;
display: flex;
}
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'>
</div>
</div>
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'>
<div></div>
</div>
</div>
<div class='container'>
<div class='item super'>
</div>
</div>
<div class='container'>
<div class='item super'>
<div></div>
</div>
</div>
I don't know if you are talking about it or not.
Your div is taking width and height as item.
so whenever you add another div it will add height of 150px.
.item div{
width: 10px;
height: 150px;
background: black;
}
Very simple rule for items of a flexbox:
Items grow value is 0 and shrink is 1 and the base-case is auto.
flex: 0 1 auto
So
.item{
width: 80px;
height: 40px; # will be used as base-case
background: blue;
margin: 5px;
/* same as
flex: 1 1 40px;
*/
}
Why does second container's item shrink? Easy. base-case is 40px or on the other hand it dose not have the class .super. Add .super and see what happens.
<div class='container'>
<div class='item'></div>
<div class='item'></div>
<div class='item'></div>
<div class='item'> # flex's item height: 40px;
<div></div> # regular div
</div>
</div>
Why the third container that has the class .super does shrink? while height: 200px and it should overflow? Easy. it is the same as: flex: 0 1 200px (this is not quite right, see the comment below, what #TemaniAfif has pointed out)
try it:
.super.item{
/* height: 200px; */
flex: 0 1 200px; # equal to height: 200px
}
now try this:
.super.item{
/* height: 200px; */
flex: 0 0 200px; # turn off auto grow / shrink
}
Why the fourth overflows?. Easy. the item has a child that is a regular div
<div class='container'>
<div class='item super'> # flex's item
<div></div> # regular div
</div>
</div>
and the height of this div is 150px
.item div{
width: 10px;
height: 150px; # remove this one, it shrinks
background: black;
}

Vertically center element with dynamic height in scroll container

I have a scroll container that's usually the size of the whole screen. Inside of it I place dynamic content. So I won't know which height it has or how many elements will be inserted.
Now I want to layout it like this:
if there is enough space, I want the whole content vertically centered inside the scroll container
if the total height of the content exceeds the height of the scroll container, I want the container to just scroll the contents like there was no centering.
I created an example where I tried to solve this problem with flexbox. With content height less than the container height it works like intended. But when the content exceeds the container height, due to justify-content, some elements of the content are cut off:
You can see on the image that the scroll container's scrollTop is all the way at the top, yet elements 1 & 2 aren't visible.
I'd like to know if there is a CSS only solution. A JS solution I could do myself but that's not what I'm after. If it's not possible, that's okay too.
.container {
display: inline-block;
width: 300px;
height: 300px;
border: 2px solid red;
overflow-y: auto;
margin: 1rem 0;
display: flex;
flex-direction: column;
justify-content: center;
}
.block {
width: 80%;
height: 3rem;
margin: 1rem auto;
background: blue;
flex-shrink: 0;
color: #fff;
text-align: center;
}
<div class="container">
<div class="block">1</div>
</div>
<div class="container">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
</div>
<div class="container">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
<div class="block">5</div>
<div class="block">6</div>
<div class="block">7</div>
<div class="block">8</div>
</div>
Try applying the overflow to an inner containing div like so:
.container {
display: inline-block;
width: 300px;
height: 300px;
border: 2px solid red;
margin: 1rem 0;
display: flex;
flex-direction: column;
justify-content: center;
}
.inner {
overflow-y: auto;
}
.block {
width: 80%;
height: 3rem;
margin: 1rem auto;
background: blue;
flex-shrink: 0;
color: #fff;
text-align: center;
}
<div class="container">
<div class="inner">
<div class="block">1</div>
</div>
</div>
<div class="container">
<div class="inner">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
</div>
</div>
<div class="container">
<div class="inner">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
<div class="block">5</div>
<div class="block">6</div>
<div class="block">7</div>
<div class="block">8</div>
</div>
</div>

How to text-align:center an absolute element on IE?

I have the code:
html:
<div class=container1>
<div class=container2>
<div class="box">
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
</div>
<div class=container2>
<div class="box">
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
</div>
<div class=container2>
<div class="box">
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
</div>
<div class=container2>
<div class="box">
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
</div>
</div>
css:
.container1 {
background: yellow;
height: 200px;
position: relative !important;
width: 260px !important;
}
.container2 {
background: blue;
border: solid 1px;
float: left !important;
height: 180px;
/*position: relative; can't use, as it would limit icons inside this container*/
text-align: center;
width: 60px;
}
.container2:hover .box {
display: inline-block;
}
.box {
background: red;
border: solid 1px;
display: none;
height: 120px;
position:absolute;
text-align: center;
top: 20px;
width: 180px !important;
}
.box:first-child {
text-align: left;
}
.icon {
border: solid 1px;
background: white;
display: inline-block;
height: 50px;
width: 50px;
}
http://jsfiddle.net/388ygc74/10/
And on IE (any version) the text-align:center does not work.
The solution to make .box width:100% is not applicable, I need it to be a fixed defined width.
Any idea?
How about using left: 30px; (since you set the width to 60px) playing with z-index and position: relative ?
(Yes, you said no position:relative; but it's working :) )
See it here
I think that's what you looking for?
left:50%
margin-left:{-50% of elementh width}px;
Add specific selector to add the element that you want to align
:nth-child(4)

Child div elements that auto-columises based on 100% parent height

I have numerous div elements that I would like to be scrolled horitonzaly rather than vertically, based on 100% parent height.
I have done a quick move up of the desired result.
As an example if the parent is 600 pixels tall, six 100px items will fit before it makes a new column and a 900px height would fit 9 items.
How can I achieve this affect? I only need it to work in Chrome is cross-browser support is not available for this.
Code for you to fiddle with, http://jsfiddle.net/yQ5AR/
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
<div class="item">16</div>
<div class="item">17</div>
<div class="item">18</div>
<div class="item">19</div>
<div class="item">20</div>
</div>
.container{
max-height: 400px;
width: 100%;
overflow: scroll;
}
.item{
height: 100px;
}
Use flexbox for this
FIDDLE
CSS
.container{
max-height: 600px;
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.item{
height: 70px;
background: silver;
width: 200px;
margin: 10px;
padding: 5px;
}
CSS columns and column-break-inside should do what you're looking for (-webkit in this case since you only care about Chrome).
http://jsfiddle.net/yQ5AR/4/
CSS
.container{
max-height: 400px;
width: 100%;
overflow: scroll;
-webkit-columns: 100px;
}
.item{
height: 100px;
-webkit-column-break-inside: avoid;
}

Resources