Using CSS flexbox and overflowing top instead of bottom - html

I'm making a "chatbox" with CSS flexbox and I'm stuck with trying to get items to overflow correctly.
I want the chat to always be in order with newest items on the bottom, like a normal chat.
The end user is able to select whether they want the chats to align to the top or to the bottom of the container.
When I have it set to bottom and can use the justify-content: flex-end property, it overflows at the top perfectly.
Here's how I'm trying to get it to work:
When the first chat comes in, it is aligned to the top of the container.
When the second chat comes in, it is under the first chat.
Eventually there will be enough messages that it overflows its container. However since I'm using the justify-content: flex-start property to align to the top, the items overflow at the bottom when instead I want the items to be pushed out the top.
How do I get the messages to move up?
<div id="main-container">
<div id="messages">
<div class="message-row">Message 1</div>
<div class="message-row">Message 2</div>
<div class="message-row">Message 3</div>
</div>
</div>
and my CSS (my CSS is a lot more complex than this so I removed what I think is unnecessary for the question but please let me know if you need to see something else)
#messages {
display: flex;
flex-direction: column;
justify-content: flex-start;
height: 95%;
box-sizing: border-box;
overflow: hidden;
}

This is how I've done it. I've created a div called message-block and aligned it to the parent using flex-end so it always sits at the bottom. This block, however, has the children aligned to the top. Because I've set the min-height to 100% it pushes its size to the parent (message-block) and the messages appear at the top. As it overflows with more messages the flex-end keeps the bottom message visible.
Took some thinking about. I not too sure I understand it myself tbh ;-)
var count = 0;
window.onload = () => {
document.getElementById('clear').addEventListener('click', (e) => {
document.querySelector(".message-block").innerHTML = "";
count = 0;
});
setInterval(appendChild, 1000);
};
function appendChild() {
let msg = document.createElement("div");
msg.className = "message";
msg.innerText = "Message " + count++;
document.querySelector(".message-block").appendChild(msg);
}
.container {
height: 160px;
overflow: hidden;
display: flex;
align-items: flex-end;
border: 1px solid gray;
}
.message-block {
width: 100%;
min-height: 100%;
}
.message {
border-radius: 0.5rem;
background-color: lightgray;
margin: 0.25rem;
padding: 0.25rem 0.5rem;
}
<div class='container'>
<div class='message-block'></div>
</div>
<button id='clear'>Clear</button>

One way to achieve this would be to set the CSS property overflow-y: scroll; on the #messages element, and then set the property align-items: flex-end; on the #messages element when the user wants to align the messages to the bottom.
This will make the messages overflow out of the top of the container, while still maintaining the latest messages at the bottom of the container when scrolled to the bottom.
Let me know if this works!

Related

Setting flex-grow: 1 causes div height to go beyond available space

I have some html like this:
.container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
padding: 10px;
background-color: aqua;
}
.box {
width: 100%;
height: 100%;
flex-grow: 1;
background-color: cadetblue;
display: flex;
flex-direction: column;
}
.fill {
flex-grow: 1;
background-color: antiquewhite;
}
.middle {
height: fit-content;
background-color: azure;
justify-self: flex-end;
}
.bottom {
height: fit-content;
background-color: darkgray;
justify-self: flex-end;
}
<div class="container">
<h3>Title</h3>
<div>Some Stuff</div>
<div class="box">
<div class="fill">Fill</div>
<div class="middle">Middle</div>
<div class="bottom">Bottom</div>
</div>
</div>
I want the divs middle and bottom to stack at the bottom of the screen, and for the div fill to, as the name suggests, fill the remaining space without pushing the middle/bottom divs off the screen or creating a scrollbar, however it doesn't display like that:
Note that the middle and bottom divs are not visible and the scrollbar created by the fill div expanding beyond the available height.
See this StackBlitz for a demo: https://stackblitz.com/edit/angular-ivy-mwtwdg?file=src/app/hello.component.scss
I had to update a lot of CSS but feel free to take a look.
The right approach to any angular project is to have clean from the very first component (app component), and cascade it down to any other component.
Demo stackblitz
EDIT : comment explanation
"The right approach" can be explained quickly like this :
html and body should be at 100% of the page
App component should be at 100% and in display block
Any component that requires some specific layout (flex, grid), should be constrained by its parent or an absolute size, and display block.
The issue with Angular is that when you create a component, it is not set to display: block. This means the component is kind of free in the DOM flow, and this results in the kind of issues you have encountered.
When you set display: block to EVERY component (you can use angular.json to make it automatic), then you have a more deterministic approach to the CSS, where what you expect is what you get.
In your case, since the components were not display:block, they could not be constrained by height, width, or their parents.
Added to that, the fact that you wrote some probelmatic CSS (for instance, the sidenav-container being 100% of the height of its parent : what about the toolbar ?), this resulted in your issue.
As a final word, when it comes to CSS in Angular, be sure to have clean CSS from the top, and when you have any issue like you did, crawl back component by component, to find and correct the unclean ones !

How to center a scaled down div within a flexbox?

I have a split screen, with a fixed right side. Left hand side will be a markdown editor, but with different configurations and styles to add to the output text.
Whereas the right hand side will basically be a preview. Left hand side is scrollable, and right hand side isn't.
After completing the form, users will be able to print out whatever they create basically. So to preview this, I created a content div (that will be printed out) with 210mm x 297mm dimensions to mimic A4 format.
What I want to do is to shrink it down using scale, to show the entire preview of the page to the user, but I want to have it vertically centered.
Here is the sandbox for it:
https://codesandbox.io/s/silly-cloud-cgsnd0?file=/index.html
And to see the actual issue, just uncomment width, height and scale, within content class.
I agree with Paulie_D.
Always give direct code snippets, in this case scale doesn't matter for you, flexbox is a responsive tool, and question is actually just how do you center that div in your setup.
To give others context this is the setup:
<div class="main-col second">
<header>...</header>
<main>
<div class="content">...</div>
</main>
<footer>...</footer>
</div>
.main-col.second {
display: flex;
align-items: center;
flex-direction: column;
background-color: #cccccc;
height: 100vh;
position: fixed;
right: 0;
top: 0;
}
.main-col.second main {
flex-grow: 1;
}
You have two options:
Apply flex-box to the main element inside the .second div.
.main-col.second main {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
Or remove the entire styling for the selector .main-col.second main and add justify-content: space-between to your .main-col.second selector.

How to avoid an extra space on the right while creating a navigation bar using flexbox (justify-content: space-between/around) properties

enter image description hereI got stack by a simple thing...
I am trying to create a simple navigation for my footer. So, I created a and placed an in it. The list contains three s and each of them has an inside. I wish my list items to be placed horizontally with spaces between / around them. Thus, I decided to use flexbox in this case. The question is that when I am setting display property value of my to flex and justify-content to center, it work predictably (i.e. all the list items sticked to each other are centered horizontally), however, as soon as I set justify-content to "space-between" or "space-around" I get an extra space to the right side of my content, which makes this space three times bigger than the one on the left side of the content.
I tried to search this topic in the history, but found nothing similar. Google search brought me a potential solution - to set flex:1 to each of the list items. But in this case I loose the gaps between the items which is not my intention.
Below I provide a picture of the problem and my testing code snippets. One more observation is that everything works great in code snippets programs (JSFiddle or Code Pen)...
Problem illustration
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.footer {
height: 100vh;
background: grey;
position: relative;
}
.container {
width: 90%;
height: 30vh;
margin: auto;
position: absolute;
top: 20%;
left: 50%;
transform: translateX(-50%);
}
.nav {
background: white;
height: 100%;
}
.list {
height: 100%;
list-style-type: none;
text-align: center;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.item {
min-width: 30%;
background: grey;
}
<div class="footer">
<div class="container">
<nav class="nav">
<ul class="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
</ul>
</nav>
</div>
</div>
Your code snippet is ok. In your screenshot it seems you have a lot more css going on, though.
I can't see the complete CSS-snippet in your screenshot and I might be completely wrong: It looks like a piece of the clearfix-hack where you are missing the ::before part.
Because adding an empty space only in ::after will have exactly the effect you are describing.
It probably is the remains of a former float-construct, so you can just remove the ::after part.

Am I using flexbox right? Can't seem to get vertical alignment to work - other threads dont seem to have answer

I am building a website from an image given to me to practice (it comes from his employer as a test). I know he mainly used flexbox in the entire site, so im trying to stick with that (havent learned grid at all). On the top of the website is a sort of 'header' that includes some button links, a logo, and a search bar in the middle. The searchbar is located vertically about halfway down the entire header.
I am trying to do that without using a margin hack, but none of the typical align or justify commands seem to work. I also set a height, still nothing. Any thoughts?
Included a height property, also tried various commands like: align-item, align-items, align-self, justify-content, etc.
#searchbar {
height: 100px;
width: 15rem;
flex: 1;
/* margin-top: 15px; */
margin-right: -5px;
text-align: center;
}
I want to move the search bar down to the middle of its parent element, but nothing seems to work.
You need to apply align-self: center to the #searchbar - asyou can see - the display: flex is applied to the parent, then align-self to the div. This centeres it withing the parent. Then you will need to apply that same logic to the contents of the searchbar div itself - in order to center them within it. and adding justify-content: center to center the content horizontally within the parent div as well.
I have applied a yellow background on the parent div, a red border on the searchbar div to demonstrate the relationship and the centering of the inner div and a blue border on the text withon the searchbar div to show its centered..
#wrapper {
height : 200px;
display: flex;
background: yellow
}
#searchbar {
height: 100px;
width: 15rem;
flex: 1;
text-align: center;
align-self: center;
border: solid 1px red;
display: flex;
align-items: center;
justify-content: center
}
#searchbar-content {
border: solid 1px blue;
}
<div id="wrapper">
<div id="searchbar">
<span id="searchbar-content">Search bar content goes here</span>
</div>

flex and overflow : weird behaviour [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 3 years ago.
EDIT: added flex-direction: column, missed it in the initial code.
When the child has overflow:auto and the parent has overflow:auto, the scrollbars appear on the child.
But when overflow:auto is removed from the parent, the scrollbars appear on the grand-parent .
html,
body {
height: 100%;
width: 100%;
overflow: hidden;
font-family: "Roboto", sans-serif;
}
body {
margin: 0;
padding: 0;
}
.App {
display: flex;
height: 100%;
}
.grand-parent {
display: flex;
flex-direction: column;
background: red;
overflow: auto;
padding: 20px;
}
.parent {
display: flex;
overflow: auto;
padding: 20px;
background: green;
}
.child {
overflow: auto;
font-size: 156px;
}
<div class="App">
<div class="grand-parent">
<div class="parent">
<div class="child">
Some content which grows bigger
</div>
</div>
</div>
</div>
Why is that? I would still expect the scrollbars to appear on the child.
How is the browser layout algorithm working here?
EDIT:
weirdly enough, the behavior seems to depend on the grand-parent having flex-direction: column. It works as I expect when flex-direction: row
tested on Chrome 75, firefox 67
This seems to have something to do with flex-direction on the grand-parent, if flex-direction is row, the horizontal scroll shows this behavior, if flex-direction is column, the vertical scroll shows this behavior
EDIT:
On further experiment, If we set min-height: 0 on parent, it behaves as expected, so this issue might be similar to
https://moduscreate.com/blog/how-to-fix-overflow-issues-in-css-flex-layouts/
https://css-tricks.com/flexbox-truncated-text/
For overflow-y, the CSS property which controls how content overflows parent vertical edges, the default value is visible. Here is how it works:
Content is not clipped and may be rendered outside the padding box's top and bottom edges.
This means that if the content doesn't fit in the box, some content will be rendered outside the box.
This property is not inherited, however. The CSS below will not set the overflow property to auto on children of div with ID parent:
var parentElem = document.getElementById('parent');
var childElem = document.getElementById('child');
console.log('overflow-y property of parent element: ' + window.getComputedStyle(parentElem).overflowY)
console.log('overflow-y property of child element: ' + window.getComputedStyle(childElem).overflowY)
#parent {
overflow: auto;
}
<div id="parent">
<div id="child">
Some content
</div>
</div>
This means that when content overflows in children boxes, scrollbars are automatically displayed by browsers on parent boxes; you will have to specify explicitly the property on children nodes as needed.