I have no idea what this is called but I want to build this nav the way it is on the picture I came pretty far using tailwind and custom css, but I'm stuck.
Does anyone know what this is called (to update the title) and how to build it?
My attempt:
.active::before {
content: "";
position: absolute;
background-color: transparent;
border-color: white;
border-width: 0 0.5rem 0.5rem 0;
width: 2rem;
height: 2rem;
right: -0.5rem;
border-radius: 0 0 100% 0;
top: -1.5rem;
}
.active::after {
content: "";
position: absolute;
background-color: transparent;
border-color: white;
border-width: 0.5rem 0.5rem 0 0;
width: 2rem;
height: 2rem;
right: -0.5rem;
border-radius: 0 100% 0 0;
bottom: -1.5rem;
}
.active-link {
display: flex;
justify-content: center;
align-items: center;
background-color: white;
border-top-left-radius: 10rem;
border-bottom-left-radius: 10rem;
width: 5rem;
height: 2rem;
}
<link href="https://unpkg.com/tailwindcss#^1.0/dist/tailwind.min.css" rel="stylesheet" />
<nav class="w-32 h-64 bg-indigo-900 rounded-xl">
<div class="flex flex-col items-center justify-between h-full py-12">
<div>
Title
</div>
<div class="w-full">
<ul class="flex flex-col items-center space-y-12 w-full">
<li class="w-full flex justify-center relative active">
<nuxt-link :to="menuItem.target" class="active-link">
<i class="text-black">Icon</i>
</nuxt-link>
</li>
</ul>
</div>
<div>
<i>Icon</i>
</div>
</div>
</nav>
This may be easier if all you need to do is add a classname to the selected element (as opposed to modifying the DOM structure whenever a new item in the navbar is clicked).
The following achieves this:
let nav = document.getElementsByClassName('navbar')[0];
for (let item of document.getElementsByClassName('item')) {
item.addEventListener('click', () => {
let selected = nav.querySelector('.item.selected');
if (selected) selected.classList.remove('selected');
item.classList.add('selected');
});
}
body { font-family: monospace; }
.navbar {
position: absolute;
left: 0; top: 0;
width: 60px; height: 100%;
padding-left: 10px;
background-color: rgba(70, 0, 170);
overflow: hidden;
}
.item {
position: relative;
height: 60px; line-height: 60px;
color: #fff;
text-align: center;
z-index: 1;
cursor: pointer;
}
.item.selected {
background-color: #fff;
border-radius: 100%;
color: #000;
}
.item.selected::before,
.item.selected::after {
content: ' '; display: block;
position: absolute;
left: 0; width: 100%; height: 100%;
pointer-events: none;
border-radius: 100%;
border: 50px solid rgba(0, 0, 0, 0);
border-right: 50px solid #fff;
margin-left: -50px;
z-index: -1;
}
.item.selected::before { bottom: 100%; margin-bottom: -50px; transform: rotate(45deg); }
.item.selected::after { top: 100%; margin-top: -50px; transform: rotate(-45deg); }
<div class="navbar">
<div class="item">(1)</div>
<div class="item">(2)</div>
<div class="item selected">(3)</div>
<div class="item">(4)</div>
</div>
That snippet is interactive, so try clicking menu items!
Note that the rounding is also very similar to the image you displayed, since we are using true circle radii.
The trick here is to add ::before and ::after elements to the selected item, and apply borders to them, remove all of the border except for one side, and finally rotate these pseudoelements so that the border goes where we want it. The following snippet demonstrates:
#keyframes styleBefore {
0% {
border: 0 solid #000;
margin-left: 0;
margin-bottom: 0;
}
20% {
border: 50px solid #000;
border-right: 50px solid #000;
margin-left: -50px;
margin-bottom: -50px;
}
40% {
border: 50px solid #000;
border-right: 50px solid #fff;
}
60% {
border: 50px solid transparent;
border-right: 50px solid #fff;
transform: rotate(0deg);
}
95% {
border: 50px solid transparent;
border-right: 50px solid #fff;
transform: rotate(45deg);
}
100% {
border: 50px solid transparent;
border-right: 50px solid transparent;
margin-left: -50px;
margin-bottom: -50px;
transform: rotate(45deg);
}
}
#keyframes styleAfter {
0% {
border: 0 solid #000;
margin-left: 0;
margin-top: 0;
}
20% {
border: 50px solid #000;
border-right: 50px solid #000;
margin-left: -50px;
margin-top: -50px;
}
40% {
border: 50px solid #000;
border-right: 50px solid #fff;
}
60% {
border: 50px solid transparent;
border-right: 50px solid #fff;
transform: rotate(0deg);
}
95% {
border: 50px solid transparent;
border-right: 50px solid #fff;
transform: rotate(-45deg);
}
100% {
border: 50px solid transparent;
border-right: 50px solid transparent;
margin-left: -50px;
margin-top: -50px;
transform: rotate(-45deg);
}
}
body { font-family: monospace; }
.navbar {
position: absolute;
left: 0; top: 0;
width: 90px; height: 100%;
padding-left: 10px;
background-color: rgba(70, 0, 170);
overflow: hidden;
}
.item {
position: relative; top: -85px;
height: 90px; line-height: 90px;
color: #fff;
text-align: center;
z-index: 1;
cursor: pointer;
font-size: 200%;
}
.item.selected {
background-color: #fff;
border-radius: 100%;
color: #000;
}
.item.selected::before,
.item.selected::after {
content: ' '; display: block;
position: absolute;
left: 0; width: 100%; height: 100%;
pointer-events: none;
border-radius: 100%;
z-index: -1;
}
.item.selected::before { bottom: 100%; animation: 10s infinite linear styleBefore; }
.item.selected::after { top: 100%; animation: 10s infinite linear styleAfter; }
<div class="navbar">
<div class="item">(1)</div>
<div class="item">(2)</div>
<div class="item selected">(3)</div>
<div class="item">(4)</div>
</div>
It's really a matter of pixels; to adjust pixel-wise the border-radius and top & bottom properties. Fiddled it.
.active::before {
content: "";
position: absolute;
background-color: transparent;
border-color: white;
border-width: 0 0.5rem 0.7rem 0;
width: 2rem;
height: 2rem;
right: -0.5rem;
border-radius: 0 0 100% 0;
top: -1.34rem;
outline: white;
}
.active::after {
content: "";
position: absolute;
background-color: #f8f8f800;
border-color: white;
border-width: 0.7rem 0.7rem 0px 0px;
width: 2rem;
height: 2rem;
right: -0.7rem;
border-radius: 0 100% 0 0;
bottom: -1.30rem;
}
.active-link {
display: flex;
float: right;
justify-content: center;
align-items: center;
background-color: white;
border-top-left-radius: 10rem;
border-bottom-left-radius: 10rem;
width: 8rem;
height: 5rem;
margin-left: 10px;
}
.active-link .text-black {
margin-left: -10px;
}
<link href="https://unpkg.com/tailwindcss#^1.0/dist/tailwind.min.css" rel="stylesheet" />
<nav class="w-24 h-64 bg-indigo-900 rounded-xl">
<div class="flex flex-col items-center justify-between h-full py-12">
<div>
Title
</div>
<div class="w-full">
<ul class="flex flex-col items-center space-y-12 w-full">
<li class="w-full flex justify-center relative active">
<nuxt-link :to="menuItem.target" class="active-link">
<i class="text-black">Icon</i>
</nuxt-link>
</li>
</ul>
</div>
<div>
<i>Icon</i>
</div>
</div>
</nav>
Related
I have been trying to add a title border with CSS. but I can't find the actual result.
.widget-title {
font-size: 1em;
border-bottom: 1px solid red;
margin-bottom: 30;
text-decoration: underline;
text-underline-offset: 1rem;
padding-bottom: 0.5rem;
text-decoration-thickness: 0.1875rem;
text-decoration-color: green;
color: black;
}
<h1 class="widget-title"> Widget title </h1>
For gray line, you have to use ::before element, hope its works
.widget-title {
font-size: 1em;
margin-bottom: 0;
color: black;
position: relative;
width: 33.33%
}
.widget-title span{
display: inline-block;
position: relative;
padding-bottom: 15px;
}
.widget-title:before{
content: "";
position: absolute;
left: 0;
bottom: 2px;
width: 100%;
background: #ccc;
z-index: -1;
height: 2px;
}
.widget-title span:before{
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background: blue;
z-index: -1;
height: 6px;
border-radius: 20px;
}
.d-flex{
display: flex;
gap: 30px
}
<div class="d-flex">
<h1 class="widget-title"> <span>Widget title</span></h1>
<h1 class="widget-title"> <span>Title sm</span></h1>
<h1 class="widget-title"> <span>Widget title long</span></h1>
</div>
.widget-title {
border-bottom: 1px solid #000;
padding: 0 0 5px;
}
Steps:
1)Add border-bottom.
2)Change the padding-bottom.
This will work. Thanks.
what I want to do is to achieve the image with css, but I could not achieve exactly what I want. Thanks in advance for your help on how to do it.
.alt {
color: white;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 130px;
background-color: #d2151e;
}
.alt:before {
content: ' ';
background: none;
display: block;
height: 0;
position: absolute;
width: 0;
top: 0;
left: 50%;
z-index: 99;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #ffffff;
}
.alt:after {
content: '';
}
<div class="alt flex">
<div class="flex w-full h-full item-center">
<div style="width: 40%">
</div>
</div>
<div class="logo">
</div>
</div>
Something like that ?
:root {
--card-width: 200px;
}
.container {
position: relative;
background-color: #E01D2B;
height: 180px;
width: 600px;
margin: auto;
overflow: hidden;
}
.arrow {
height: 100px;
width: 100%;
background-color: white;
display: flex;
justify-content: center;
align-items: flex-end;
}
.arrow::after {
display: block;
background-color: white;
width: 20px;
height: 20px;
bottom: 0;
content: '';
transform: translate(calc(var(--card-width) / -2), 50%) rotate(45deg);
}
.card {
display: block;
position: absolute;
bottom: 0;
right: 0;
width: calc(var(--card-width) + 40px);
height: 110px;
border-top-left-radius: 1em;
background-color: #eee;
transform: translate(34px) skewX(-30deg);
}
<div class="container">
<div class="arrow"></div>
<div class="card"></div>
</div>
Here is what you can do with css
.alt {
color: white;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 130px;
background-color: #d2151e;
}
.alt:before {
content: ' ';
background: none;
display: block;
height: 0;
position: absolute;
width: 0;
top: 0;
left: 32%;
z-index: 99;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #ffffff;
}
.alt:after {
content: '';
}
.logo {
background: #f0f0f0;
width: 40%;
height: 160px;
position: absolute;
right: -100px;
box-shadow: -2px 1px 4px #757575c9;
top: -30px;
border-radius: 15px 0 0 0;
-webkit-transform: skew(-45deg);
-moz-transform: skew(-45deg);
-ms-transform: skew(-45deg);
transform: skew(-45deg);
overflow: hidden;
}
and html is
<div class="alt flex">
<div class="flex w-full h-full item-center">
<div style="width: 40%">
</div>
</div>
<div class="logo">
</div>
Is it possible to style the following HTML structure to the image shown below with CSS only?
<div class="xyz-dialog">
<div class="title"><span> Tip Title</span></div>
<div class="body"> <span>Description</span></div>
</div>
Required design:
You can do it as below if we can add a container div in the HTML:
.container{
background: gray;
padding: 16px 10px;
width:max-content;
}
.xyz-dialog {
background: white;
padding: 1rem;
border-radius: 8px;
position: relative;
width: 300px;
}
.xyz-dialog::after {
content: "";
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid white;
position: absolute;
top: 100%;
}
.body {
margin-top:8px;
color: gray;
font-size: 15px
}
<div class= "container">
<div class="xyz-dialog">
<div class="title"><span> Tip Title</span></div>
<div class="body"> <span>Description</span></div>
</div>
You can do it as below if we cannot touch the HTML structure:
.xyz-dialog {
padding: 1rem;
border-radius: 8px;
position: relative;
width: 300px;
}
.xyz-dialog::after {
content: "";
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid white;
position: absolute;
top: calc(100% -1rem);
left: 2rem;
}
.xyz-dialog::before {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: gray;
z-index: -1;
}
.title {
padding: 1rem;
background: white;
border-radius: 10px 10px 0 0;
margin: 0 0 -5px 0;
}
.body {
color: gray;
font-size: 15px;
background: white;
margin: 0;
padding: 1rem;
border-radius: 0 0 10px 10px;
}
<div class="xyz-dialog">
<div class="title"><span> Tip Title</span></div>
<div class="body"> <span>Description</span></div>
</div>
You can use after and border.
.xyz-dialog::after{
content: "";
border-top: 12px solid #f1f1f1;
border-right: 8px solid transparent;
border-left: 8px solid transparent;
position: absolute;
bottom: -12px;
left: 4%;
}
.xyz-dialog{
width: 50%;
background: #f1f1f1;
border-radius: 0.3em;
padding: 5px 30px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
box-sizing: border-box;
flex-direction: column;
}
<div class="xyz-dialog">
<div class="title"><span> Tip Title</span></div>
<div class="body"> <span>Description</span></div>
</div>
Little late. Two Boxes. For the small noise you use the css pseudo class after.
body {
background-color: #999;
}
.wrapper {
padding:20px;
}
h3 {
margin:0;
color: #000;
}
.bubble {
position: relative;
background: white;
color: #999;
font-family: Arial;
font-size: 16px;
text-align: left;
width: 250px;
height: 120px;
border-radius: 10px;
padding: 0px;
}
.bubble:after {
content: '';
position: absolute;
display: block;
width: 0;
z-index: 1;
border-style: solid;
border-width: 0 20px 20px 0;
border-color: transparent #fff transparent transparent;
bottom: -16px;
left: 17%;
margin-left: -10px;
}
<div class="bubble">
<div class="wrapper">
<h3>title</h3>
<div>content</div>
</div>
</div>
i have a box and i need to put smooth triangle bottom of the div but i couldn't achieve as i want how can i do this like below image ?
.slide-box {
position: relative;
display: inline-block;
background: #e41113;
border: 1px solid #df2b2c;
border-radius: 6px;
}
.slide-box a {
display: block;
color: #fff;
text-decoration: none;
padding: 12px 10px;
}
.slide-box:after {
content: '';
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
width: 0;
height: 0;
border-top: 25px solid #df2b2c;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
}
<div class="slide-box">
<a href="#">
I'm a super <br>box!
</a>
</div>
I'm not sure that you'll be able to complete what you want with ::after.
But probably you can use transition rotate and scale on absolute positioned element in the bottom.
Here's the concept:
.slide-box {
position: relative;
display: inline-block;
background: #e41113;
border: 1px solid #df2b2c;
border-radius: 6px;
width: 145px;
height: 70px;
}
.slide-box a {
display: block;
color: #fff;
background: #e41113;
display: block;
text-decoration: none;
padding: 12px 10px;
z-index:1000;
}
.slide-box .corner {
position: absolute;
top: 70px;
left: 0px;
width: 103px;
height: 103px;
background-color: #e41113;
transform-origin: top left;
transform: scale(1, 0.25) rotate(-45deg);
border-radius: 6px;
}
<div class="slide-box">
<a href="#">
I'm a super <br>box!
</a>
<div class="corner"></div>
</div>
Of course the main task will be positioning.
So there you need 2 prerequisitions:
With "transform-origin: top left;" you need to keep top of the .corner == height of your main container (don't know why, but bottom:0 not works, maybe youll resolve
this)
The .corner should be square (width=height), and to keep it smooth you need to maintain ratio width(.corner) = width(.slide-box)*sqrt(2). Means width of your corner`s diagonal should be equal to width of main container.
Here is a way to do:
.container {
width: 300px;
}
.slide-box {
height: 200px;
width: 100%;
position: relative;
background-color: #df2b2c;
text-align: left;
margin-left: 70px;
margin-bottom: -75px;
border-radius: 0 0 25% 25%;
}
.slide-box a {
display: block;
color: #fff;
text-decoration: none;
padding: 12px 10px;
}
.corner {
position: relative;
background-color: #df2b2c;
text-align: left;
margin-left: 95px;
}
.corner:before,
.corner:after {
content: '';
position: absolute;
background-color: inherit;
}
.corner,
.corner:before,
.corner:after {
width: 165px;
height: 165px;
border-top-right-radius: 30%;
}
.corner {
transform: rotate(-120deg) skewX(-30deg) scale(1,.866);
}
.corner:before {
transform: rotate(-135deg) skewX(-45deg) scale(1.414,.707) translate(0,-50%);
}
.corner:after {
transform: rotate(135deg) skewY(-45deg) scale(.707,1.414) translate(50%);
}
<div class="container">
<div class="slide-box">
<a href="#">
I'm a super <br>box!
</a>
</div>
<div class="corner"></div>
</div>
So I am trying to do conditional rendering and i've narrowed it down to the outside parent <div> tag being the culprit. So, I removed the conditional rendering and am trying to figure out why my card styling is being altered. Below I posted screenshots with and without parent div tag.
return (
<div>
<div className="card" id="chatcard">
<div className="card-body">
<h5 className="card-title">{this.props.user.user}</h5>
<div className="card-text">
<ChatList
user={this.props.user}
socket={this.props.socket}
currentUser={this.props.currentUser}
/>
</div>
</div>
<div className="card-footer">
<small className="text-muted">
<form>
<ChatField
user={this.props.user}
socket={this.props.socket}
chatusers={this.props.index}
/>
</form>
</small>
</div>
</div>
</div>
);
CSS
.chat {
color: white;
}
.chat .dropdown-toggle:after {
content: none;
}
.userbutton {
size: 2px;
}
.card {
color: black;
}
.card-text {
overflow: auto;
height: 10rem;
}
.onlinebar {
position: "absolute";
color: red;
bottom: 0;
left: 0;
}
#chatbtn {
color: black;
width: 200px;
margin-left: 5px;
margin-top: 0px;
}
.chatcollapse {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#chatHeader {
margin: 0px;
padding: 0px;
}
#chatcard {
width: 2rem;
}
.card-deck .card {
max-width: calc(25% + 80px);
}
.card-body {
padding: 0px;
margin: 0px;
}
.bubble-r {
align-items: flex-end;
position: relative;
background: #0072c6;
max-width: 100px;
padding: 5px;
font-family: arial;
margin: 0 auto;
font-size: 14px;
color: white;
border-radius: 6px;
}
.bubble-r:after,
.bubble-r:before {
left: 100%; /*change this from right to left*/
top: 42%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.bubble-r:after {
border-color: rgba(200, 200, 204, 0);
border-left-color: #0072c6; /*change this from right to left */
border-width: 8px;
margin-top: -3px;
}
.bubble-r:before {
border-color: rgba(200, 204, 0, 0);
border-left-color: #0072c6; /*change this from right to left*/
border-width: 8px;
margin-top: -3px;
}
.bubble {
position: relative;
background: #cad5d7;
max-width: 100px;
padding: 5px;
font-family: arial;
margin: 0 auto;
font-size: 14px;
border-radius: 6px;
}
.bubble:after,
.bubble:before {
right: 100%;
top: 42%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.bubble:after {
border-color: rgba(255, 255, 204, 0);
border-right-color: #cad5d7;
border-width: 8px;
margin-top: -3px;
}
.bubble:before {
border-color: rgba(255, 204, 0, 0);
border-right-color: #cad5d7;
border-width: 8px;
margin-top: -3px;
}
#chatcard {
width: 40rem;
}
I adjusted the width within this and it worked. It's odd that adding the div tag caused this.