Hello I am trying to design a chat room and am stuck on the css of speech bubbles.
What I want
Blue speech bubbles on the right and grey ones on the left.
At the moment
I tried several answers I found on SO like position relative/absolute. But none of the answers worked for me. If someone can help me here itd be great.
Html
<div class="card-body p-3 pt-0">
<div class="my-1 rounded-lg ">
<div class="position-relative w-100">
#foreach ($chats as $chat)
<p class="text-xs">
{{$chat->created_at}} # {{$chat->name}}
</p>
<div class="border-0 {{ $chat->user_identifier == 'SELF' ? 'chat-bubble-send' : 'chat-bubble-receive' }}">
<p class="text-sm ">
{{ $chat->message }}
</p>
</div>
#endforeach
</div>
</div>
</div>
Css
.chat-bubble-receive p {
background: #42a5f5;
color: #fff !important;
border-radius: 20px 20px 3px 20px;
display: block;
max-width: 75%;
padding: 7px 13px 7px 13px;
}
.chat-bubble-send p {
background: #f1f1f1;
color: #000 !important;
border-radius: 20px 20px 20px 3px;
display: block;
max-width: 75%;
padding: 7px 13px 7px 13px;
position: absolute;
left: 0;
}
.card-body {
flex: 1 1 auto;
padding: 1rem 1rem;
}
When the message is short
Chat messages using CSS Flex
Inside a flex parent, to determine the left/right position of the message elements โ use margin-(left/right) set to auto
When using position:absolute make sure to use position:relative; (or any other position other than static) on a parent element.
Use bottom: 100% to position the absolute time details on top of the first message.
"Hide" display:none; by default the "name+datetime" pseudo element, but show it display:block; only for the first message in group by using :first-child and the + next sibling combinator selector
You could use the data-* attribute to store the extra details (time etc) and use a pseudo element like ::before to than populate it with that value using content: attr(data-time)
/* QuickReset */ * {margin: 0; box-sizing: border-box;}
.chat {
--rad: 20px;
--rad-sm: 3px;
font: 16px/1.5 sans-serif;
display: flex;
flex-direction: column;
padding: 20px;
max-width: 500px;
margin: auto;
}
.msg {
position: relative;
max-width: 75%;
padding: 7px 15px;
margin-bottom: 2px;
}
.msg.sent {
border-radius: var(--rad) var(--rad-sm) var(--rad-sm) var(--rad);
background: #42a5f5;
color: #fff;
/* moves it to the right */
margin-left: auto;
}
.msg.rcvd {
border-radius: var(--rad-sm) var(--rad) var(--rad) var(--rad-sm);
background: #f1f1f1;
color: #555;
/* moves it to the left */
margin-right: auto;
}
/* Improve radius for messages group */
.msg.sent:first-child,
.msg.rcvd+.msg.sent {
border-top-right-radius: var(--rad);
}
.msg.rcvd:first-child,
.msg.sent+.msg.rcvd {
border-top-left-radius: var(--rad);
}
/* time */
.msg::before {
content: attr(data-time);
font-size: 0.8rem;
position: absolute;
bottom: 100%;
color: #888;
white-space: nowrap;
/* Hidden by default */
display: none;
}
.msg.sent::before {
right: 15px;
}
.msg.rcvd::before {
left: 15px;
}
/* Show time only for first message in group */
.msg:first-child::before,
.msg.sent+.msg.rcvd::before,
.msg.rcvd+.msg.sent::before {
/* Show only for first message in group */
display: block;
}
<div class="chat">
<div data-time="16:35" class="msg sent">Hi!<br>What's up?</div>
<div data-time="Anna 16:36" class="msg rcvd">Hi dear! <br>Doing some CSS research, you?</div>
<div data-time="16:38" class="msg sent">Also learning some cool CSS stuff ๐ฆ</div>
<div data-time="16:38" class="msg sent">!!</div>
<div data-time="16:38" class="msg sent">Up for a coffee today? โ</div>
<div data-time="Anna 16:40" class="msg rcvd">It would be a pleasure!</div>
<div data-time="Anna 16:40" class="msg rcvd">๐</div>
</div>
I suggest using flex magic with a new row-div wrapping every bubble.
.row:nth-of-type(2n) {
display: flex;
justify-content: flex-end;
}
.bubble {
display: inline-block;
padding: 5px;
}
<div class="page-wrapper">
<div class="bubble-wrapper">
<div class="row">
<div class="bubble">
<p>First bubble</p>
<small>Details</small>
</div>
</div>
<div class="row">
<div class="bubble">
<p>Second bubble</p>
<small>Details</small>
</div>
</div>
<div class="row">
<div class="bubble">
<p>Third bubble</p>
<small>Details</small>
</div>
</div>
<div class="row">
<div class="bubble">
<p>Fourth bubble</p>
<small>Details</small>
</div>
</div>
</div>
</div>
Related
I would like the layout to look as so, but also be responsive (so that the heading + paragraph both stay positioned to the left of the icon).
CSS:
.feature {
position: relative;
border: 1px solid #000;
}
.circle {
height: 2.5rem;
width: 2.5rem;
background-color: #64beeb;
border-radius: 50%;
float: right;
}
.icon {
font-size: 1.75rem;
color: #fff;
}
HTML:
<div class="feature">
<div class="text text-right">
<p class="h2">Diversity of Content</p>
<p class="descrip">Dive deep and share themed content across various topics based on your audience</p>
</div>
<div class="circle text-center">
<i class="icon ion-android-bulb"></i>
</div>
</div>
CODEPEN DEMO
add this to .circle and remove float:right; Then it will be absolutely positioned from the parent relative container.
position: absolute;
top: 10px;
right: 10px;
.feature {
position: relative;
border: 1px solid #000;
}
.circle {
position: absolute;
top: 10px;
right: 10px;
height: 2.5rem;
width: 2.5rem;
background-color: #64beeb;
border-radius: 50%;
}
.icon {
font-size: 1.75rem;
color: #fff;
}
<div class="feature">
<div class="text text-right">
<p class="h2">Diversity of Content</p>
<p class="descrip">Dive deep and share themed content across various topics based on your audience</p>
</div>
<div class="circle text-center">
<i class="icon ion-android-bulb"></i>
</div>
</div>
And you could add padding-right: 50px; to .feature so the icon (blueih circle) will not be over text. See here https://jsfiddle.net/ymzofeph/
One option is to use flexbox. You can add display: flex to the container (.feature). Add flex: 1 to the text. To create some space around the icon you can use a margin value you find suitable.
.feature {
position: relative;
border: 1px solid #000;
/* for demo */
text-align: right;
display: flex;
}
.text {
flex: 1;
}
.circle {
height: 2.5rem;
width: 2.5rem;
background-color: #64beeb;
border-radius: 50%;
margin: 1rem;
}
.icon {
font-size: 1.75rem;
color: #fff;
}
<div class="feature">
<div class="text text-right">
<p class="h2">Diversity of Content</p>
<p class="descrip">Dive deep and share themed content across various topics based on your audience</p>
</div>
<div class="circle text-center">
<i class="icon ion-android-bulb"></i>
</div>
</div>
<div class="feature">
<div class="circle text-center">
<i class="icon ion-android-bulb"></i>
</div>
<div class="text text-right">
<p class="h2">Diversity of Content</p>
<p class="descrip">Dive deep and share themed content across various topics based on your audience</p>
</div>
</div>
<style>
.circle{
float:right;
width:40px;
height:40px;
margin:0 0 0 20px;
}
.text{
overflow:hidden;
}
</style>
Put the float:right div before the .text-right div. Then add padding-right:2.5rem; to the .text-right div.
Example
I have the following page (see code snippet below). I would like to position each of the items, so that when it is a full web page, the elements are i their desired positions, but as soon as it is viewed on narrow aspect ratio (e.g. mobile phone), then the items need to fold under each other.
I can get a full web page working, using position: absolute;. I can position the items where I want. But the problem is then on a mobile devise, the items overlap each other. So I figure I need to use position: relative;.
position: relative; allows the items to fold beneath each other on a narrow browser. However, I cannot seem to position the items where I want.
In the below example, I would like to position the items as follows:
logo
title
text screen-print-one
google apple web screen-print-two
Terms of Service some#email.com
body {
font-family: "proxima-nova" ,"Helvetica", sans-serif;
}
/* logo */
.wz-logo {
text-align: center;
padding: 20px 20px 0px 20px;
}
/* title */
.wz-title {
font-size: 120%;
color: #B2D137;
text-align: center;
padding: 0 20px 40px 30px;
}
/* text */
.text-description {
padding-left: 10%;
padding-bottom: 20px;
padding-top: 20px;
width: 500px;
}
/* screen-prints */
.screen-prints {
position: relative;
float: right;
padding-right: 10%;
}
.screen-print1 {
position: relative;
top: 100px;
left: 0;
z-index: 2;
}
.screen-print2 {
position: relative;
top: -430px;
left: -120px;
z-index: 1;
}
/* store */
.store-container {
display: flex;
justify-content: left;
align-items: center;
padding-left: 10%;
}
.store-container .apple, .img-container .google, .img-container .web {
padding: 10px;
padding-left: 20px;
}
.store-container .google {
padding-top: 0px;
padding-left: 0px;
padding-right: 0px;
margin-top: 10px;
}
.store-container .apple {
padding-top: 8px;
padding-left: 0px;
padding-right: 0px;
}
.store-container .web {
padding-top: 15px;
}
/* footer */
footer .terms, footer .contact {
display:inline-block;
padding-bottom: 30px;
padding-right: 10px;
padding-left: 10px;
}
footer .contact {
padding-right: 40px !important;
}
footer a {
color: white;
text-decoration: none;
font-size: 14px;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
}
footer {
position:absolute;
bottom:0;
right: 0;
}
<body class="background-image">
<div class="wz-logo">
logo
</div>
<div class="wz-title">
title
</div>
<div class="text-description">
text
</div>
<div class="screen-prints">
<div class="screen-print1">screen-print-one
</div>
<div class="screen-print2">screen-print-two
</div>
</div>
<div class="store-container">
<div class="google">
google
</div>
<div class="apple">
apple
</div>
<div class="web">
web
</div>
</div>
<footer>
<div class="terms">
Terms of Service
</div>
<div class="contact">
some#email.com
</div>
</footer>
</body>
If anyone can assist with how I can position the items, I would appreciate the help. (As you can see my main problem is trying to position the screen-print-one & screen-print-two).
Thanks
hmm there are a bunch of problems with your html logic. too many divs and not wrapped logically . but i made what i could with it
see below. or jsFiddle
.wz-logo,.wz-title {
width:100%;
float:left;
text-align:center;
}
.left_text {
float:left;width:50%;
}
.left_text .store-container div{
display:inline
}
.screen-prints {
float:right;
width:50%;
text-align:right;
}
footer {
float:left;
width:100%;
text-align:right
}
footer div {
display:inline
}
#media only screen and (max-width: 460px) {
.left_text,.screen-prints,footer {
width:100%;
text-align:center;
}
}
<body class="background-image">
<div class="wz-logo">
logo
</div>
<div class="wz-title">
title
</div>
<div class="left_text">
<div class="text-description">
text
</div>
<div class="store-container">
<div class="google">
google
</div>
<div class="apple">
apple
</div>
<div class="web">
web
</div>
</div>
</div>
<div class="screen-prints">
<div class="screen-print1">screen-print-one
</div>
<div class="screen-print2">screen-print-two
</div>
</div>
<footer>
<div class="terms">
Terms of Service
</div>
<div class="contact">
some#email.com
</div>
</footer>
</body>
i suggest you use bootstrap for responsiveness . it's much easier to use
If you hover over the "This is Broken!" tag, the adjacent "Damn" tag wraps to the next line. This is because the "This is Broken!" tag increased in size and is being constrained by the container.
Is it possible to prevent this wrapping?
The tags and parent container size are dynamic, so I can't easily group rows of tags together in a containing element that has the "white-space: nowrap" property. Any tag that is being hovered on or any adjacent tag can be the one that wraps to the next line. If possible, I would like to retain the same space between tags before-and-after hover.
main {
width: 160px;
}
.material-tag-wrapper {
margin: 1px 3px 1px 0;
display: inline-block;
}
.material-tag-wrapper.closeable:hover .material-tag {
padding-right: 26px;
}
.material-tag-wrapper.closeable:hover .material-tag-remove {
opacity: 1;
padding-right: 10px;
}
.material-tag {
background-color: blue;
color: white;
font-weight: 400;
cursor: pointer;
border-radius: 3px;
padding: 2px 8px;
text-transform: uppercase;
font-size: 10px;
transition: .1s all;
display: inline-block;
position: relative;
text-align: center;
}
.material-tag-remove {
color: #3C4858;
cursor: pointer;
font-size: .8em;
position: absolute;
top: 4px;
right: 0;
opacity: 0;
text-align: right;
text-decoration: none;
width: 100%;
z-index: 2;
}
.material-tag-remove:before {
content: "x";
color: white;
}
<main>
<div class="material-tag-wrapper closeable">
<div class="material-tag">
Beautiful
<div class="material-tag-remove"></div>
</div>
</div>
<div class="material-tag-wrapper closeable">
<div class="material-tag">
Works
<div class="material-tag-remove"></div>
</div>
</div>
<div class="material-tag-wrapper closeable">
<div class="material-tag">
This is Broken!
<div class="material-tag-remove"></div>
</div>
</div>
<div class="material-tag-wrapper closeable">
<div class="material-tag">
Damn
<div class="material-tag-remove"></div>
</div>
</div>
<div class="material-tag-wrapper closeable">
<div class="material-tag">
I Work!
<div class="material-tag-remove"></div>
</div>
</div>
</main>
Since you add padding-right: 26px; to material-tag-wrapper:hover, you could apply the same rule for main (or any wrapper you choose):
main:hover {
width: 186px; /* base width of 160px + 26px */
}
I currently have an event tracker made using html and css. My issue is that I would like to get ride of display: flex; due to browser-compatibility issues. Is there an alternative to achieve the same result? I tried using display:inline-block because without flex all steps were coming in different lines.
HTML:
<div class="container">
<div class="row event">
<div class="col-xs-3 event-step">
<p class="event-stepnum">Step 1</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
<div class="col-xs-3 event-step complete">
<p class="event-stepnum">Step 2</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
<div class="col-xs-3 event-step">
<p class="event-stepnum">Step 3</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
</div>
</div>
CSS:
.event > .event-step {
padding: 0;
position: relative;
}
.event > .event-step .event-stepnum {
color: #595959;
font-size: 16px;
margin-bottom: 5px;
}
.steps .step-on,
.steps .step-done {
background-color: #1b7e28;
color: #1b7e28;
border: 1px solid transparent;
}
.progress {
position: relative;
border-radius: 0px;
height: 5px;
box-shadow: none;
margin: 20px 0;
}
.progress > .progress-bar {
width: 0px;
box-shadow: none;
background: #fbe8aa;
}
.event-step.complete > .progress > .progress-bar {
width: 100%;
}
.row {
display:flex;
}
JSFiddle Demo
Just replace the display:flex by display:inline-block and give your step divs a fixed width:
.event > .event-step {
padding: 0;
position: relative;
width: 200px;
}
.row {
display: inline-block;
}
https://jsfiddle.net/onk2cqhg/
Good day! I'm having a struggle to aligned the jumbtron to my calendar icon. And the elements of the jumbtron is not inside of it. Can someone help me how to solve this? Ideas? i just started studying bootstrap and css.
Here's the picture.
here is my html code.
<div class="events">
<div class="container">
<div class="row">
<div class= "col-sm-4 col-xs-25">
<h4 id="event"><i class="fa fa-calendar" aria-hidden="true"></i> Upcoming Events</h4>
<hr class="carved">
<div class="date">
<span class="month">August</span>
<h1 class="day">28</h1>
</div>
<div class="container">
<div class="jumbotron">
<h4>Sample Title</h4>
<p>IT Thesis defense</p>
<h6>7:00 AM - 8:00 PM</h6>
</div>
</div>
<hr class="divider">
<div class="date">
<span class="month">August</span>
<h1 class="day">28</h1>
</div>
<hr class="divider">
<div class="date">
<span class="month">August</span>
<h1 class="day">28</h1>
</div>
</div>
<div class= "col-sm-8 col-xs-25">
<h4 id="event"><i class="fa fa-newspaper-o" aria-hidden="true"></i> Latest News</h4>
<hr class="carved">
</div>
</div>
</div>
</div>
here is my css
#event {
color: #a92419;
}
hr.carved {
clear: both;
float: none;
width: 100%;
height: 2px;
border: none;
background: #ddd;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0.5, rgb(126,27,18)),
color-stop(0.5, rgb(211,45,31))
);
background-image: -moz-linear-gradient(
center top,
rgb(126,27,18) 50%,
rgb(211,45,31) 50%
);
}
.date {
display: block;
width: 60px;
height: 60px;
margin-bottom: 20px;
background: #fff;
text-align: center;
font-family: 'Helvetica', sans-serif;
position: relative;
}
.date .month {
background: #a92419;
display: block;
padding-bottom: 5px;
padding-top: 5px;
color: #fff;
font-size: 10px;
font-weight: bold;
border-bottom: 2px solid #a92419;
box-shadow: inset 0 -1px 0 0 #a92419;
}
.date .day {
display: block;
margin: 0;
padding-bottom: 10px;
padding-top: 5px;
text-align: center;
font-size: 20px;
color:#a92419;
box-shadow: 0 0 3px #ccc;
position: relative;
}
.date .day::after {
content: '';
display: block;
height: 95%;
width: 96%;
position: absolute;
top: 3px;
left: 2%;
z-index: -1;
box-shadow: 0 0 3px #ccc;
}
.date .day::before {
content: '';
display: block;
height: 90%;
width: 90%;
position: absolute;
top: 6px;
left: 5%;
z-index: -1;
}
.jumbotron {
width: 300px;
height: 100px;
margin:none;
}
.jumbotron p {
font-size:12px;
}
The .container class carries its own width(s) and is intended to be used as a outer wrapper for your layout. Because of this, they do not tend to nest well. The one you have as a sibling of your .date classed elements is breaking the layout.
As for the spacing of the .jumbotron contents, Bootstrap assigns some pretty dramatic padding to that class by default. Consider overwriting that with your own values in your .jumbotron rule. The other issue โ the .jumbotron contents bleeding out of their container โ that is a result of the height: 100px you are setting. You can stop the contents from taking up space beyond the boundaries of the .jumbotron by adding/modifying its overflow property. This may be a matter of opinion but I think it is usually better to avoid setting height in the CSS and let the contents define the size of the container โ especially in cases where the content is CMS/client driven.
If you remove the .container, youโll still have the problem of the .date and .jumbotron stacking vertically. To address that, you might consider treating Date element as .row with a column for your .date element, and a column for that Dateโs event(s).
<hr class="carved">
<div class=โrowโ><!-- the Date wrapper -->
<div class="col-sm-4">
<div class="date">
<span class="month">August</span>
<h1 class="day">28</h1>
</div>
</div>
<div class="col-sm-8"><!-- this column holds all the Events for this Date -->
<div class="jumbotron">
<h4>Sample Title</h4>
<p>IT Thesis defense</p>
<h6>7:00 AM - 8:00 PM</h6>
</div>
</div>
</div>
Note: The new structure will require a bit of adjustment to some of your CSS width properties, and the col- device/sizes I put on the Date and Event columns are just examples โ size as needed.
<div class="container">
<div class="row">
<div class="col-md-2">
<h4 id="event"><i class="fa fa-calendar" aria-hidden="true"></i> Upcoming Events</h4>
<hr class="carved">
<div class="date">
<span class="month">August</span>
<h1 class="day">28</h1>
</div><!-- date -->
</div><!-- md2 -->
<div class="col-md-10">
<h4 id="event"><i class="fa fa-newspaper-o" aria-hidden="true"></i> Latest News</h4>
<hr class="carved">
<div class="jumbotron">
<h4>Sample Title</h4>
<p>IT Thesis defense</p>
<h6>7:00 AM - 8:00 PM</h6>
</div><!-- jumbo -->
</div><!-- md10 -->
</div><!-row>
</div><!-- container -->
+
#event {
color: #a92419;
}
hr.carved {
clear: both;
float: none;
width: 100%;
height: 2px;
border: none;
background: #ddd;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0.5, rgb(126,27,18)),
color-stop(0.5, rgb(211,45,31))
);
background-image: -moz-linear-gradient(
center top,
rgb(126,27,18) 50%,
rgb(211,45,31) 50%
);
}
.date {
display: block;
width: 60px;
height: 60px;
margin-bottom: 20px;
background: #fff;
text-align: center;
font-family: 'Helvetica', sans-serif;
position: relative;
}
.date .month {
background: #a92419;
display: block;
padding-bottom: 5px;
padding-top: 5px;
color: #fff;
font-size: 10px;
font-weight: bold;
border-bottom: 2px solid #a92419;
box-shadow: inset 0 -1px 0 0 #a92419;
}
.date .day {
display: block;
margin: 0;
padding-bottom: 10px;
padding-top: 5px;
text-align: center;
font-size: 20px;
color:#a92419;
box-shadow: 0 0 3px #ccc;
position: relative;
}
.date .day::after {
content: '';
display: block;
height: 95%;
width: 96%;
position: absolute;
top: 3px;
left: 2%;
z-index: -1;
box-shadow: 0 0 3px #ccc;
}
.date .day::before {
content: '';
display: block;
height: 90%;
width: 90%;
position: absolute;
top: 6px;
left: 5%;
z-index: -1;
}
Result