Chat list messages can't scroll up using flexbox - html

I'm trying to make messages shows from bottom to top, like on whatsapp, you will see the latest messages and it will start from bottom and for older messages you need to scroll up.
I'm using display: flex; and justify-content: flex-end; which seems to display correctly (from bottom).
But the problem is that I can't scroll to top, it does not let me.
How can I fix this?
body {
background-color: #000;
height: 100%;
width: 100%;
}
.box {
width: 800px;
height: 200px;
background-color: lightblue;
}
.container {
width: 100%;
height: 100%;
overflow-y: auto;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.header {
display: flex;
justify-content: center;
align-items: center;
margin: 10px 0;
background: red;
}
.message {
margin: 10px;
}
.message.player {
background-color: #ccc
}
.message.me {
background-color: lightgreen;
}
<body>
<div class="box">
<div class="container">
<div class="header">
<span>Yesterday</span>
</div>
<div class="message player">
<span>Message from friend 1</span>
</div>
<div class="message player">
<span>Message from friend 2</span>
</div>
<div class="message player">
<span>Message from friend 3</span>
</div>
<div class="header">
<span>Today</span>
</div>
<div class="message me">
<span>Message from me 1</span>
</div>
<div class="message me">
<span>Message from me 2</span>
</div>
<div class="message me">
<span>Message from me 3</span>
</div>
</div>
</div>
</body>

There is a hack how to do it with CSS with flex-direction: column-reverse for a wrapper, which I attached as an example. But it probably would be better to make it explicitly with JavaScript using Window.scroll() method.
.test {
width: 30px;
height: 30px;
}
.test:nth-of-type(2n + 1) {
background: yellow;
}
.wrapper {
height: 300px;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
<div class="wrapper">
<div class="div">
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
<div class="test">5</div>
<div class="test">6</div>
<div class="test">7</div>
<div class="test">8</div>
<div class="test">9</div>
<div class="test">10</div>
<div class="test">11</div>
<div class="test">12</div>
<div class="test">13</div>
<div class="test">14</div>
<div class="test">15</div>
<div class="test">16</div>
<div class="test">17</div>
<div class="test">18</div>
<div class="test">19</div>
<div class="test">20</div>
</div>
</div>

It is because you are forcing your .container div to be of fixed height (i.e 100% of its parent). Remove the height: 100%; and overflow-y: auto; from .container and set overflow-y: auto; on your .box div.
body {
background-color: #000;
height: 100%;
width: 100%;
}
.box {
width: 800px;
height: 200px;
background-color: lightblue;
overflow-y: auto;
}
.container {
width: 100%;
/* height: 100%;
overflow-y: auto; */
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.header {
display: flex;
justify-content: center;
align-items: center;
margin: 10px 0;
background: red;
}
.message {
margin: 10px;
}
.message.player {
background-color: #ccc
}
.message.me {
background-color: lightgreen;
}

Related

Problem laying out items in an image gallery

I am having trouble laying out my items in a gallery. I would like to be able to display an image in a horizontal or vertical format and have it fit within a fixed 300px x 300px box and align to the bottom of the box. I would like the "attribution" to line up with the right edge of the image. Here is a picture of the desired layout.
Picture of desired layout
This is the html:
.gallery {
display:flex;
gap: 10px;
}
.gallery_item_square {
height: 450px;
width: 300px;
background: brown;
}
.gallery_square {
height: 300px;
display: flex;
background: green;
}
.gallery_description {
height:auto;
width:100%;
}
.image_attribution {
display:flex;
flex-direction:column;
align-items:flex-end;
}
.image_square {
width: 100%;
height: 100%;
background: black;
display:flex;
flex-direction:column;
align-items:flex-end;
}
.gallery_attribution {
width: 100%;
background: orange;
display: flex;
}
.image {
height:100%;
background: green;
width:
}
.image_contain {
width: 100%;
height: 100%;
object-fit:contain;
object-position: bottom;
}
.attribution {
float:right;
}
<div class="gallery">
<div class="gallery_item_square">
<div class="gallery_square">
<div class="image_attribution">
<div class="image_square">
<div class="image">
<img class="image_contain" src="https://acrossky.github.io/Images/3W6A8814.jpg">
<span class="attribution"> ARC/Qedema</span>
</div>
</div>
</div>
</div>
<div class="gallery_description">
<p>This is a description</p>
</div>
</div>
<div class="gallery_item_square">
<div class="gallery_square">
<div class="image_attribution">
<div class="image_square">
<div class="image">
<img class="image_contain" src="https://acrossky.github.io/Images/3W6A8817.jpg">
<span class="attribution"> ARC/Qedema</span>
</div>
</div>
</div>
</div>
<div class="gallery_description">
<p>This is a description</p>
</div>
</div>
</div>
I am unable to make the image fit within the box. Ive tried use "object-fit:contain" but to no avail. I would be grateful for any help you can offer.
Update: the code is almost working. The last item is to make the attribution align with edge of the image. align attribution to edge of image Here is the latest version of the code in Codepen.
https://codepen.io/acrossky/pen/KKoNdPX
Maybe something like this:
.gallery {
display: flex;
gap: 10px;
}
.gallery_item_square {
height: 450px;
width: 300px;
background: brown;
}
.gallery_square {
height: 300px;
width: 100%;
display: flex;
justify-content: center;
background: green;
}
.gallery_description {
width: 100%;
height: auto;
}
.image_attribution {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.image_square {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.gallery_attribution {
width: 100%;
background: orange;
display: flex;
justify-content: center;
}
.image {
height: 100%;
width: 100%;
}
.image_contain {
width: 100%;
height: 100%;
object-fit: contain;
object-position: bottom;
}
.attribution {
display: block;
}
<div class="gallery">
<div class="gallery_item_square">
<div class="gallery_square">
<div class="image_attribution">
<div class="image_square">
<div class="image">
<img class="image_contain" src="https://acrossky.github.io/Images/3W6A8814.jpg">
<span class="attribution"> ARC/Qedema</span>
</div>
</div>
</div>
</div>
<div class="gallery_description">
<p>This is a description</p>
</div>
</div>
<div class="gallery_item_square">
<div class="gallery_square">
<div class="image_attribution">
<div class="image_square">
<div class="image">
<img class="image_contain" src="https://acrossky.github.io/Images/3W6A8817.jpg">
<span class="attribution"> ARC/Qedema</span>
</div>
</div>
</div>
</div>
<div class="gallery_description">
<p>This is a description</p>
</div>
</div>
</div>

Visible overflow on X axis, but auto/scroll on axis Y

To keep things neat and short:
https://jsfiddle.net/m53ockLu/
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: 150px;
overflow-x: scroll;
overflow-y: auto;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
width: 20px;
background: green;
}
.first {
position: relative;
display: block;
height: 20px;
width: 100px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
position: absolute;
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
Is it possible to keep the red container scrollable on vertical axis, and at the same time make the purple (.second-absolute) element overflow this red container horizontally? I'm totally out of ideas, I thought that overflow-x & overflow-y should do the trick, but no dice.
Thank you very much for any help.
Is it possible to keep the red container scrollable on vertical axis, and at the same time make the purple (.second-absolute) element overflow this red container horizontally?
No.
I tried Ethan's suggestion and couldn't get the purple box to visibly overflow the scrollbar:
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: 150px;
overflow-y: scroll;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
width: 20px;
background: green;
}
.first {
position: relative;
display: block;
height: 20px;
width: 100px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
position: absolute;
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
I don't think the browser will let you overflow the scrollbar, I even put z-index, explicitly said to visibly overflow, played around with the position property etc.
Consider this example of letting the content dictate the size:
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: max-content;
overflow-y: auto;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
background: green;
}
.first {
display: block;
height: 20px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
You made the parent div sidebar have overflow-x: scroll;, overflow-y: auto;. Instead, make each child have its own overflow properties instead of the parent.

CSS flex centering to parent full width

I'm trying to center two buttons within the center of their parent element. The problem is that the first element has content in the beginning and end, which causes flex to center to that, messing up the alignment of the whole.
#container {
background-color: green;
width: 100%;
}
#d1 {
height: 50px;
display: flex;
}
#d2 {
background-color: blue;
width: 50px;
height: 50px;
}
#d3 {
background-color: red;
}
<div id="container">
<div id="d1">
<p>This is some text</p>
<input type="button">
<div id="d2"></div>
</div>
<div id="d3">
<input type="button">
</div>
</div>
Add a display: flex property on #container
#container {
background-color: green;
width: 100%;
display:flex
}
#d1 {
height: 50px;
display: flex;
}
#d2 {
background-color: blue;
width: 50px;
height: 50px;
}
#d3 {
background-color: red;
}
<div id="container">
<div id="d1">
<p>This is some text</p>
<input type="button">
<div id="d2"></div>
</div>
<div id="d3">
<input type="button">
</div>
</div>
You need justify-content: center; along with display:flex; on parent div.
#container {
background-color: green;
width: 100%;
display: flex;
justify-content: center;
}
#d1 {
height: 50px;
display: flex;
}
#d2 {
background-color: blue;
width: 50px;
height: 50px;
display: flex;
}
#d3 {
background-color: red;
}
<div id="container">
<div id="d1">
<p>This is some text</p>
<input type="button">
<div id="d2"></div>
</div>
<div id="d3">
<input type="button">
</div>
</div>
I don't know how much this code will be help you. Just try to give it more better view so that you can control the alignment properly along with button height and width. Just hope it helps you.
#container {
background-color: green;
width: 100%;
display: flex;
}
#d1 {
width: 33.33%;
display: flex;
padding: 0 10px 0 10px
}
#d2 {
width: 33.33%;
display: flex;
padding: 0 10px 0 10px text-align:center;
}
#d3 {
width: 33.33%;
display: flex;
padding: 0 10px 0 10px
}
#d2>input {
background-color: blue;
width: 100%;
vertical-align: middle;
}
#d3>input {
background-color: red;
vertical-align: middle;
width: 100%;
padding: 0 10px 0 10px
}
<div id="container">
<div id="d1">
<p>This is some text</p>
</div>
<div id="d2"><input type="button"></div>
<div id="d3">
<input type="button">
</div>
</div>

Align elements with different heights on the same row

I am trying to display multiple circles on the same horizontal axis but with different width and height. The problem is that the circles are shrinked.
body,
html {
height: 100%;
margin: 0;
padding: 0;
}
.circles-container {
display: table;
border-spacing: 40px;
}
.row {
display: table-row;
}
.circle {
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 50%;
text-align: center;
vertical-align: middle;
display: table-cell;
}
.cell {
display: table-cell;
}
.big-circle {
width: 300px;
height: 300px;
}
<div class="circles-container">
<div class="row">
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="big-circle circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="big-circle circle">
<span>TEXT</span>
</div>
</div>
</div>
</div>
JSFIDDLE: https://jsfiddle.net/cxuxgy0u/
You should not use the table layout for this. Your HTML does not semantically represent a table, so table element is worng to use.
What you want to do can be achieved with Flexbox.
article {
display: flex;
align-items: center;
}
article > div + div {
margin-left: 1rem;
}
article > div {
flex-shrink: 0;
height: 4rem;
width: 4rem;
border-radius: 50%;
border: solid 1px black;
display: flex;
justify-content: center;
align-items: center;
}
article > div:nth-child(2) {
height: 6rem;
width: 6rem;
}
<article>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
<div><span>TEXT</span></div>
</article>
You might want to read more about Flexbox on MDN.
A simple flexbox solution. Just be sure to set flex-shrink to 0, because the initial value is 1, which allows flex items to shrink when necessary to prevent overflowing the container.
body,
html {
height: 100%;
margin: 0;
padding: 0;
}
.circles-container {
display: flex;
align-items: center;
}
.circle {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
flex: 0 0 100px; /* flex-shrink: 0, to disable shrinking default */
height: 100px;
border-radius: 50%;
margin: 20px;
border: 1px solid #000;
}
.big-circle {
flex-basis: 300px;
height: 300px;
}
<div class="circles-container">
<div class="circle">
<span>TEXT</span>
</div>
<div class="circle">
<span>TEXT</span>
</div>
<div class="big-circle circle">
<span>TEXT</span>
</div>
<div class="circle">
<span>TEXT</span>
</div>
<div class="big-circle circle">
<span>TEXT</span>
</div>
</div>
https://jsfiddle.net/cxuxgy0u/7/
Try this:
HTML
<div class="container">
<div class="circle">Text</div>
<div class="circle">Text</div>
<div class="circle">Text</div>
<div class="circle">Text</div>
</div>
CSS
.container {
display:flex;
justify-content: space-around;
align-items: center;
height: 100vh;
}
.circle {
background: white;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.circle:nth-child(odd) { width: 100px; height: 100px; }
.circle:nth-child(even) { width: 200px; height: 200px; }
Uses flexbox and is the simplest way to achieve what you want.
Here's a fiddle https://jsfiddle.net/itsag/sk3tdo4L/
Hope it helps!
I think your problem is found in the styling.
For each circle, you need to remove the style
display:table-cell
vertical-align: middle;
and then u need to bring in line-height. The line-height should be equal to the height of the circle, for for the smaller circle, you will have
line-height:100px //this brings the text to the middle of the circle vertically.
Then also, you need to increase the border-radius from 50% to 100%
border-radius:100%;
Therefore, your css will not look like this
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.circles-container{
display: table;
border-spacing: 40px;
}
.row {
display: table-row;
}
.circle {
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 100%;
text-align: center;
line-height:100px;
}
.cell {
display: table-cell;
}
.big-circle {
width: 300px;
height: 300px;
line-height:300px;
}
This should help you.
Flexbox:
container {
display: flex;
justify-content: center;
}
If you want space between the pictures, use:
margin-left:
or
margin-right:
try this
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.circles-container{
display: table;
border-spacing: 40px;
}
.row {
display: flex;
}
.circle {
padding: 40px 30px;
border: 1px solid #000;
border-radius: 50%;
text-align: center;
vertical-align: middle;
position: relative;
}
.cell {
}
.big-circle {
padding: 150px;
}
<div class="circles-container">
<div class="row">
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="big-circle circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="circle">
<span>TEXT</span>
</div>
</div>
<div class="cell">
<div class="big-circle circle">
<span>TEXT</span>
</div>
</div>
</div>
</div>

Nested flexbox height issue in IE

I have nested flexboxes with some images inside, it looks good in Chrome, but in IE you can see the borders on the flex-item-wrapper are not flush against the bottom of the image. By the way, in the layout I will sometimes have several flex-row with many pictures.
.flex-list {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
}
.flex-item-wrapper {
width: 100%;
border: 1px solid green;
}
.flex-item {
height: 100%;
width: 100%;
border: 1px solid blue;
}
.picture {
width: 100%;
}
<div class="flex-list">
<div class="flex-row">
<div class="flex-item-wrapper">
<div class="flex-item">
<a href='#'>
<img class="picture" src="http://www.picgifs.com/clip-art/cartoons/super-mario/clip-art-super-mario-832109.jpg" alt="">
</a>
</div>
</div>
<div class="flex-item-wrapper"></div>
<div class="flex-item-wrapper"></div>
<div class="flex-item-wrapper"></div>
</div>
</div>
This seems to be working:
.flex-row {
display: flex;
flex: 0 0 auto; /*added*/
}
or
.flex-row {
display: flex;
height: 100%; /*added*/
}
See simplified demo:
.flex-list {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex: 0 0 auto;
}
.flex-item {
flex: 1;
border: 1px solid blue;
}
.picture {
width: 100%;
height: auto;
}
<div class="flex-list">
<div class="flex-row">
<div class="flex-item">
<a href='#'>
<img class="picture" src="http://www.picgifs.com/clip-art/cartoons/super-mario/clip-art-super-mario-832109.jpg" alt="">
</a>
</div>
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>
</div>
The problem seems due to the nesting flexbox. This fixes it:
.flex-row {
width: 100%;
align-self: flex-start;
}
.flex-list {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
width: 100%;
align-self: flex-start;
}
.flex-item-wrapper {
width: 100%;
border: 1px solid green;
}
.flex-item {
height: 100%;
width: 100%;
border: 1px solid blue;
}
.picture {
width: 100%;
}
<div>
<div class="flex-list">
<div class="flex-row">
<div class="flex-item-wrapper">
<div class="flex-item">
<a href='#'>
<img class="picture" src="http://www.picgifs.com/clip-art/cartoons/super-mario/clip-art-super-mario-832109.jpg" alt="">
</a>
</div>
</div>
<div class="flex-item-wrapper"></div>
<div class="flex-item-wrapper"></div>
<div class="flex-item-wrapper"></div>
</div>
</div>
<div></div>
</div>