I have chat and I need to scroll all content to bottom.
I want to use justify-content: flex-end and to have vertical scrollbar.
.session-textchat {
height: 320px;
background: #fff;
display: -webkit-flex;
display: flex;
-webkit-align-items: flex-end;
align-items: flex-end;
-webkit-justify-content: space-between;
justify-content: space-between;
-webkit-flex-direction: column;
flex-direction: column;
}
.session-textchat .past-messages {
width: 100%;
max-width: 980px;
margin: 0 auto;
height: 83.92%;
overflow-y: auto;
padding: 30px 0 0;
display: -webkit-flex;
display: flex;
-webkit-align-items: flex-end;
align-items: flex-end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
-webkit-flex-direction: column;
flex-direction: column;
}
.session-textchat .past-messages .receiver,
.session-textchat .past-messages .sender {
width: 100%;
min-height: 47px;
margin: 0 0 20px;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}
.session-textchat .past-messages .receiver .message,
.session-textchat .past-messages .sender .message {
position: relative;
padding: 17px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.session-textchat .past-messages .receiver {
text-align: left;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
.session-textchat .past-messages .receiver .message {
background: #f4f4f4;
color: #535353;
}
.session-textchat .past-messages .sender {
text-align: right;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
.session-textchat .past-messages .sender .message {
background: url('../img/rgbapng/0050ff26.png');
background: rgba(0, 80, 255, 0.15);
color: #0050ff;
}
<div class="session-textchat">
<div class="past-messages">
<div class="receiver">
<span class="message">
Good afternoon David. Welcome to your appointment! How are you today?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
</div>
</div>
Example is here.
Is it possible?
Or please give me better solution.
Thanks in advance!
Srdjan
I just had to face this issue myself and, after concluding it is a bug, I came up with a workaround.
In summary, don't use justify-content: flex-end but rather put a margin-top: auto on the first child. Unlike flex-end this doesn't break the scrollbar functionality, and it bottom-aligns the contents when they're not overflowing the container.
Example based on #SrdjanDejanovic's fiddle is at https://jsfiddle.net/peter9477/4t5r0t5b/
In case the example isn't available, here's the relevant CSS:
#container {
overflow-y: auto;
display: flex;
flex-flow: column nowrap;
/* justify-content: flex-end; DO NOT USE: breaks scrolling */
}
#container > :first-child {
margin-top: auto !important;
/* use !important to prevent breakage from child margin settings */
}
An alternative workaround that I believe I've also used is to add an extra container for the scrollbar. Use the flex-end on the inner container and have the outer container handle the scrolling. I generally dislike workarounds that require adding dummy elements though, so I prefer my CSS-only solution above.
Probably you've already solved this, but I faced this problem too and found a solution by trial and error, so I'm going to share it.
Having parent container's display set to flex display: flex and child's items align to flex-end align-items: flex-end will prevent overflow-y: auto to work.
Instead, you can leave you can use next CSS properties for your parent container (in your case session-textchat):
display: flex;
flex-direction: column-reverse; /* 'column' for start, 'column-reverse' for end */
overflow-y: scroll; /* or overflow-y: auto ... */
This will make your child div appear on the bottom of parent container (it will act like flex-end) and enable vertical scroll if content height is bigger than parent container.
I made a little jsfiddle for you if this sounds confusing:
https://jsfiddle.net/lbartolic/9od4nruy/3/
In jsfiddle you can see header part, content part and footer. Container has fixed height and each part takes required height to fill the container. Content part _b__content will be scrollable if its content is taller than _b__content's height.
I hope this will help someone.
Cheers.
Also There is also another Solution
Remove the justify-content and add flex: 1 1 auto; property to the first element(create an empty div)
Old
HTML
<div class="content-reversed">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
New
HTML
<div class="content-reversed">
<div class="fix"></div> //add this dummy div
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
}
.content-reversed .fix {
flex: 1 1 auto;
}
It seems to be a common bug among the browsers.
You should distribute your style onto 2 containers: the outer will be scrolled, and the inner will be a flex container. Also, you need some js to keep your message list scrolled to bottom while adding new messages.
Here is an example of code:
markup:
<div id='outer'>
<div id='inner-scroll'>
<div id='inner-flex'>
<div class='flex-item'>Item 1</div>
<div class='flex-item'>Item 2</div>
...
</div>
</div>
style:
#inner-scroll {
height: 100%;
overflow: auto;
}
#inner-flex {
display: flex;
flex-direction: column;
justify-content: flex-end;
min-height: 100%;
}
.flex-item { /*nothing*/ }
JS:
function messagePushCallback()
{
var scrollable=document.getElementById('inner-scroll');
scrollable.scrollTo(0, scrollable.scrollHeight-scrollable.clientHeight);
}
// for an example
chat.onMessagePush(messagePushCallback);
window.addEventListener('load', messagePushCallback);
In JS, scrollable.scrollHeight shows the whole height of the element, including the space beyond its visible part, while scrollable.clientHeight is for the height of the visible part.
You have to turn .session-textchat into a flex column then margin-top: auto on .past-messages to send it to the bottom. Then play with overflow-y: scroll and some jQuery:
function updateScroll() {
$("#chat").animate({ scrollTop: $('#chat').prop("scrollHeight")}, 1000);
}
updateScroll();
$("#send_button").on('click', updateScroll);
.session-textchat {
display: flex;
flex-direction: column;
height: 300px;
margin-bottom: 30px;
background: #fff;
overflow-y: scroll;
}
.session-textchat .past-messages {
margin-top: auto;
width: 100%;
max-width: 980px;
}
.session-textchat .past-messages .receiver,
.session-textchat .past-messages .sender {
width: 100%;
min-height: 47px;
margin: 0 0 20px 0;
}
.session-textchat .past-messages .receiver .message,
.session-textchat .past-messages .sender .message {
position: relative;
padding: 15px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.session-textchat .past-messages .receiver {
text-align: left;
}
.session-textchat .past-messages .receiver .message {
background: #f4f4f4;
color: #535353;
}
.session-textchat .past-messages .sender {
text-align: right;
}
.session-textchat .past-messages .sender .message {
background: url("../img/rgbapng/0050ff26.png");
background: rgba(0, 80, 255, 0.15);
color: #0050ff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div id="chat" class="session-textchat">
<div class="past-messages">
<div class="receiver">
<span class="message">
Good afternoon David. Welcome to your appointment! How are you today?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="5" id="msg"></textarea>
</div>
<div class="form-group text-center">
<button href="#" id="send_button" class="btn btn-success">Send message</button>
</div>
</div>
Look at this full-screen jsFiddle.
This solution worked for me:
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
Related
I currently have a problem with nesting a flex box layout. I have a parent flex container and four separate containers within it, so far the other 3 column containers work correctly. However when I try to place another container underneath the main one it simply moves to the right side.
.container-wrap {
display: flex;
justify-content: center;
}
.container-leftbar {
display: flex;
height: 100%;
gap: 10px;
padding: 10px;
flex: 1;
align-items: center;
justify-content: center;
flex-direction: column;
max-width: fit-content;
}
.container-main {
display: flex;
height: 100%;
gap: 10px;
padding: 10px;
flex: 1;
align-items: center;
justify-content: center;
flex-direction: column;
max-width: fit-content;
}
.container-main2 {
display: flex;
height: 100%;
gap: 10px;
padding: 10px;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.container-rightbar {
display: flex;
height: 100%;
gap: 10px;
padding: 10px;
align-items: center;
justify-content: center;
flex-direction: column;
max-width: fit-content;
}
<!--flex wrap-->
<div class="container-wrap">
<!--left column-->
<div class="container-leftbar">
<div class="1a">123</div>
<div class="1b">123</div>
<div class="1c">123</div>
</div>
<!--1 middle body-->
<div class="container-main">
<div class="2a">123</div>
<div class="2b">123</div>
</div>
<!--2 middle body-->
<div class="container-main2">
<div class="3a">123</div>
<div class="3b">123</div>
</div>
<!--right column-->
<div class="container-rightbar">
<div class="3a">123</div>
<div class="3b">123</div>
<div class="3c">123</div>
</div>
</div>
I tried to manually place the the top and left margin of the main box however I only really was able to achieve the top margin placing. I'm still somewhat new to using flex so any sort of help is appreciated.
Edit: In order to make it easier to work with:
Sandbox
I have been stuck for 3 days with this issue so I post here in hope someone can help me find a solution.
I am making the following table (not a <table>, made with divs) since I didn't find any library to get this kind of calendar, which displays every day on a year,its purpose is to show vacations taken by each employee (that are blurred on the left).
I'm trying to use the position:fixed and other solutions to keep the employees column fixed as well as the top yellow rows while I scroll over the grid, however, I'm unable to get the intended effect.
Note that this is a react Component, so for some reason if I use position fixed, it leaves the parent component to be fixed to the main window.
This is the Component on the parent: (I did it this way as I expect to call <VisorVacaciones> inside other components with different sizes)
<div style={{width:"inherit",height:"400px",maxHeight:"400px",marginTop:"15px"}}>
<VisorVacaciones empleados={empleados} years={"2022"} vacas={vacasSelectedEmpleado}/>
</div>
This is the render of the component:
<div className='visorVMainDiv'>
<div id="columna_der_calendar_datos" className='calendario_y_celdas'>
<div id="elemento_emp" className='visorV_nombres_emp visorV_grow3'>
Empleados
</div>
<div id="cabeceras" className='visorV_cabeceras_vertical'>
<div id="meses" className='visorV_cabeceras_horizontal'>
{Array(12).fill(null).map((el,i)=>{
var month_css_width= MonthWidth(i+1,years)+"rem";
return (
<div style={{outline:"1px solid black",minWidth:month_css_width,alignItems:'center',justifyContent:'center',display:'flex',boxSizing: "border-box",backgroundColor: '#f8af07'}}>
{moment("01/01/"+years).add(i,"months").format("MMMM")}
</div>)
})}
</div>
<div id="diassemana" className='visorV_cabeceras_horizontal'>
{Array(daysOfYear(years)).fill(null).map((el,i)=>{
return (
<div style={{outline:"1px solid black",minWidth: universalSize,alignItems:'center',justifyContent:'center',display:'flex', boxSizing: "border-box",backgroundColor: '#f8af07'}}>
{moment("01/01/"+years).add(i,"days").format("dd")}
</div>)
})}
</div>
<div id="dias" className='visorV_cabeceras_horizontal'>
{Array(daysOfYear(years)).fill(null).map((el,i)=>{
return (
<div style={{outline:"1px solid black",minWidth: universalSize,alignItems:'center',justifyContent:'center',display:'flex', boxSizing: "border-box",backgroundColor: '#f8af07'}}>
{moment("01/01/"+years).add(i,"days").format("D")}
</div>)
})}
</div>
</div>
</div>
<div id="data" className='visorV_cabeceras_vertical'>
{empleados?.map((emp)=>{
return (
<div className='visorV_empleado_y_casillas_horizontal'>
<div id="elemento_emp" className='visorV_nombres_emp'>
{String(emp.nombre+" "+emp.apellidos).length <= 25 ?
emp.nombre+" "+emp.apellidos
: String(emp.nombre+" "+emp.apellidos).substring(0,25)+"..."}
</div>
<div className='visorV_empleado_y_casillas_horizontal'>
{Array(daysOfYear(years)).fill(null).map((arr,index)=>{
return <C estado={vacas!==null && index===0 ? "cyan": "pink"}</C>
})}
</div>
</div>
)})}
</div>
</div>)
And CSS rules
.visorVMainDiv{
display:flex;
flex-direction: column;
align-items:flex-start;
justify-content:flex-start;
width: 100%;
height:100%;
border:2px solid #f8af07;
font-size: 0.8rem;
overflow-y: hidden;
overflow-x: scroll;
}
.Columna_empleados{
display: flex;
width: 200px;
height:100%;
flex-direction: column;
}
.calendario_y_celdas{
display: flex;
width: 100%;
height:100%;
flex-direction: row;
}
.visorV_vertical{
display: flex;
flex-direction: column;
}
.visorV_cabeceras_horizontal{
display: flex;
width: 100%;
min-height: 1rem;
}
.visorV_cabeceras_vertical{
display: flex;
width: 100%;
flex-direction: column;
}
.datos_scroll{
overflow-y: visible;
}
.visorV_grow3{
display: flex;
justify-content: center;
min-height: 3rem !important;
align-items: center;
}
.visorV_nombres_emp{
min-width: 200px;
height: 1rem;
min-height: 1rem;
z-index:1;
outline: 1px solid black;
position: sticky;
}
.visorV_empleado_y_casillas_horizontal{
display: flex;
width: 100%;
}
Please have a look at this Vuetify fiddle: https://jsfiddle.net/L4r5aftq/
<div id="app">
<div class="address-card-container" style="background-color: pink;">
<v-card>
<div class="card-content-container">
<div class="icon-container" style="width: 30px;">
<v-icon>calendar</v-icon>
</div>
<div style="margin-left: 20px;">
<p><strong>Our Home</strong></p>
<p>123 4th Avenue N</p>
</div>
</div>
</v-card>
<v-divider horizontal class="mx-4"></v-divider>
<v-card class="add-property-card" style="margin: auto;">
<div class="card-content-container">
<div class="icon-container" style="width: 15px"><v-icon>add</v-icon></div>
<div class="add-property-container"><p>Add a property</p></div>
</div>
</v-card>
</div>
</div>
.address-card-container {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
margin-bottom: 60px;
align-items: stretch!important;
.card {
border: 1px solid #ccc;
width: 50%;
height: 100% !important;
min-height: 100% !important;
.card-content-container {
min-height: 50px;
display: flex;
flex-direction: row;
justify-content: center;
margin: 30px 7%;
.icon-container {
.v-icon {
height: 50px;
width: 100%;
color: #009FD4;
}
}
.add-property-container {
margin-left: 20px;
display: flex;
flex-direction: column;
justify-content: center;
}
}
}
.add-property-card {
cursor: pointer;
}
}
It consists of two cards inside a flex box configured as row and space-between:
I am trying to set the height of each card to take up 100% of the flex box, but it is not working.
If you go to the fiddle, you'll see that I set height: 100%!important and min-height: 100%!important. I also set align-items: stretch!important in the flex box. But the card on the right just doesn't want to take up the full height of the flex box.
How can I make the cards take up the full height of the flex box?
I'm trying to make my css with flexbox, so I followed some articles and tried to set my elements like this example:
the elements 1 & 2 are in another container
I'm trying to set the two elements (1 and 3) to be next each other as the second example (The first is what I have now and the other is what I'm trying to achieve.)
but I can't find a good way with the Flexbox since I set the container to flex-direction: column;
<div class="container">
<div class="sub-ctn">
<h5 class="1"><span>♦ </span>{{ text }}</h5>
<span class="2">{{ value }}</span>
<div class="3">
<h5>{{ text }}
</div>
</div>
</div>
CSS:
.container {
margin-right: 2.5%;
direction: rtl;
}
.sub-ctn {
display: flex;
flex-flow: row;
margin-top: 1%;
flex-direction: column;
}
.1 {
width: 100%;
direction: rtl;
text-align: right;
}
.2 {
float: right;
/* text-align: right; */
}
.3 {
margin-left: 1%;
display: flex;
flex-direction: column;
}
let me know if another information is needed
Don't use float and flex together. Flex alone will be much easier and better.
.cont{
display: flex;
width: 80%;
border: 1px solid black;
padding: 10px;
}
.left-cont{
height: 100%;
flex-grow: 1;
}
.right-cont{
flex-grow: 1;
display: flex;
flex-direction: column;
}
.item{
text-align: center;
border: 1px solid black;
margin: 3px;
}
<div class="cont">
<div class="left-cont">
<div class="item">3</div>
</div>
<div class="right-cont">
<div class="item">1</div>
<div class="item">2</div>
</div>
</div>
I would like to align a div in the parent container by allowing the user to select the following options:
Top Left
Top Middle
Top Right
Left Middle
Centered
Right Middle
Bottom Left
Bottom Middle
Bottom Right
While I find a lot of resources how to vertically and horizontally align using flexbox, I am wondering if somebody has created a simple collection of CSS-classes I could easily apply.
Edit:
The basic markup is very simple, just a button:
<div>
<div class="btn">This is my button</div>
</div>
Now to get to "Right Middle" I'd ideally to do something like:
<div class="vertical-align-middle horizontal-align-right">
<div class="btn">This is my button</div>
</div>
You can position elements in this way by creating one container element with 3 sub-containers for each row with following css.
display: flex;
flex-direction: column;
justify-content: space-between;
This will position rows at top, middle and bottom of container. Next you can can use this css for each row and that will position divs at left, center and right of row.
display: flex;
justify-content: space-between;
body,
html {
margin: 0;
padding: 0;
}
.content {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.row {
display: flex;
justify-content: space-between;
}
.box {
border: 1px solid black;
}
<div class="content">
<div class="top row">
<div class="box">Top left</div>
<div class="box">Top center</div>
<div class="box">Top right</div>
</div>
<div class="middle row">
<div class="box">Middle left</div>
<div class="box">Middle center</div>
<div class="box">Middle right</div>
</div>
<div class="bottom row">
<div class="box">Bottom left</div>
<div class="box">Bottom center</div>
<div class="box">Bottom right</div>
</div>
</div>
If you have single element in container then you can use different combinations of align-items and justify-content to position element but that also depends on flex-direction (by default is row). So for example if you want to position element at bottom-center you can use
display: flex;
align-items: flex-end;
justify-content: center;
body,
html {
margin: 0;
padding: 0;
}
.content {
height: 100vh;
display: flex;
align-items: flex-end;
justify-content: center;
}
.btn {
border: 1px solid black;
}
<div class="content">
<div class="btn">Button</div>
</div>
Take a look at my example, you need to create classes for every position, then use a little jQuery to make it changed dynamically.
(function() {
$(".select-box").on("change", function() {
var $selected = $(this).find("option:selected").val();
$("#content").removeClass().addClass($selected);
});
})();
.select-box {
position: absolute;
top: 100px;
left: 100px;
}
#content {
display: flex;
width: 600px;
height: 400px;
padding: 20px;
}
.box {
width: 50px;
height: 50px;
background-color: fuchsia;
}
#content.top-left {
justify-content: flex-start;
align-items: flex-start;
}
#content.top-middle {
justify-content: center;
align-items: flex-start;
}
#content.top-right {
justify-content: flex-end;
align-items: flex-start;
}
#content.left-middle {
justify-content: flex-start;
align-items: center;
}
#content.centered {
justify-content: center;
align-items: center;
}
#content.right-middle {
justify-content: flex-end;
align-items: center;
}
#content.bottom-left {
justify-content: flex-start;
align-items: flex-end;
}
#content.bottom-middle {
justify-content: center;
align-items: flex-end;
}
#content.bottom-right {
justify-content: flex-end;
align-items: flex-end;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="content">
<div class="box"></div>
</div>
<select class="select-box">
<option value="top-left">Top Left</option>
<option value="top-middle">Top Middle</option>
<option value="top-right">Top Right</option>
<option value="left-middle">Left Middle</option>
<option value="centered">Centered</option>
<option value="right-middle">Right Middle</option>
<option value="bottom-left">Bottom Left</option>
<option value="bottom-middle">Bottom Middle</option>
<option value="bottom-right">Bottom Right</option>
</select>
The morass library might be useful.
$ mkdir test-project
$ npm init
$ npm install morass
$ edit index.html
$ serve
where index.html is:
<html>
<head>
<style>
.big { height: 200px; width: 200px; outline: 1px red solid; }
.small { height: 100px; width: 100px; outline: 1px green solid; }
</style>
<link rel='stylesheet' href='./node_modules/morass/dist/index.css'/>
</head>
<body>
<div class='big flex align-left align-bottom'>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<div class='small'></div>
</div>
</body>
</html>
You can replace align-left with align-center or align-right, and align-bottom with align-middle or align-top, etc.
This morass library is based on what are called "micro-classes". For instance, you could also add a vertical class to make the flex items go top to bottom, or for multiple items, justify to spread them out.