I'm trying to make a button that other options pop out of when you hover over it. I've been searching for a way to do something like the screenshot below, but I wasn't able to do it. It's for a web page, so it needs to be done using HTML, CSS, and jQuery.
So we add the CSS rules, set the position fixed, 50px from bottom and 50px from the right. Add the cursor:pointer so it will look like a button. Then we add the <div class=”button iconbutton”> to wrap the fontawesome plus icon. iconbutton is to create the circle icon button with pink color and have shadow under it.
Add the floating action button to your layoutThe size of the FAB, using the app:fabSize attribute or the setSize() method. The ripple color of the FAB, using the app:rippleColor attribute or the setRippleColor() method. The FAB icon, using the android:src attribute or the setImageDrawable() method.
If you want to move the button to the right, you can also place the button within a <div> element and add the text-align property with its "right" value to the "align-right" class of the <div>.
Floating action buttons (or FAB) are: “A special case of promoted actions. They are distinguished by a circled icon floating above the UI and have special motion behaviors, related to morphing, launching, and its transferring anchor point.”
The best tutorial for this purpose that I have found so far: https://www.youtube.com/watch?v=iYFNaeEeCDI
Working demo example: https://verkkonet.com/downloads/demo.php?id=c9
.fab-container {
position: fixed;
bottom: 50px;
right: 50px;
z-index: 999;
cursor: pointer;
}
.fab-icon-holder {
width: 50px;
height: 50px;
border-radius: 100%;
background: #016fb9;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}
.fab-icon-holder:hover {
opacity: 0.8;
}
.fab-icon-holder i {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 25px;
color: #ffffff;
}
.fab {
width: 60px;
height: 60px;
background: #d23f31;
}
.fab-options {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 70px;
right: 0;
opacity: 0;
transition: all 0.3s ease;
transform: scale(0);
transform-origin: 85% bottom;
}
.fab:hover+.fab-options,
.fab-options:hover {
opacity: 1;
transform: scale(1);
}
.fab-options li {
display: flex;
justify-content: flex-end;
padding: 5px;
}
.fab-label {
padding: 2px 5px;
align-self: center;
user-select: none;
white-space: nowrap;
border-radius: 3px;
font-size: 16px;
background: #666666;
color: #ffffff;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
margin-right: 10px;
}
<div class="fab-container">
<div class="fab fab-icon-holder">
<i class="fas fa-question"></i>
</div>
<ul class="fab-options">
<li>
<span class="fab-label">Documentation</span>
<div class="fab-icon-holder">
<i class="fas fa-file-alt"></i>
</div>
</li>
<li>
<span class="fab-label">Video Tutorials</span>
<div class="fab-icon-holder">
<i class="fas fa-video"></i>
</div>
</li>
<li>
<span class="fab-label">Live Chat</span>
<div class="fab-icon-holder">
<i class="fas fa-comments"></i>
</div>
</li>
<li>
<span class="fab-label">Feedback</span>
<div class="fab-icon-holder">
<i class="fas fa-comment-alt"></i>
</div>
</li>
</ul>
</div>
The entire example is from: https://verkkonet.com/. The YouTube video tutorial is great to learn how to do this.
I revisited my solution today and added the final touches to those parts I left incomplete yesterday. I also added several additional enhancements and stylistic improvements. Now, for the #mega-button
parent, it uses a gradient background but then smoothly transitions to a faded blue-gray background color by using an oversized gradient and transitioning the background-position
property. I also decrease the size of this button on hover as I rotate and increase the size of the child .sub-button
elements, to give the appearance of the .sub-button
elements rolling out from behind the #mega-button
.
To make the transition feel more smooth and natural, I also added a slight transition-delay
between each of the .sub-button
elements to create a waterfall effect rather than them all rolling out on top of each other. I achieved this and also the unique position per .sub-button
using a for loop in my SCSS, and iterating in reverse for the transition-delay
to have the right-most button animate out first.
I also utilize some glassmorphism styles to give the #mega-button
just the slightest bit of a a frosted glass look as the buttons roll out from behind it: backdrop-filter: blur(4px)
When you click on any of the child buttons, they trigger their associated modal via :target
. The modals themselves all offer several pure-HTML/CSS ways to close the modal:
Each modal is entirely unique and is triggered by its associated .sub-button
. I built a bit of a system behind the modal styles as well, with global styles for the .modal-content
, .modal-header
, and .modal-body
, as well as contextual styles for the .modal-close
class, which displays as the clickable/cancellable backdrop behind the modal when inserted within the modal's main element, whereas it displays as the "x" in the top-right corner when included within the .modal-content
element. Clicking either will close the modal.
Two final nice-to-haves I added today:
#mega-button
. This tooltip cannot be clicked and does not functionally obstruct any content behind it as it has its pointer-events
property set to none
. This fades to opacity: 0
both when the #mega-button
or any of its descendants are being hovered over or when a modal is open, via the general sibling combinator (~
).Here is the finished product:
@charset "UTF-8";
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
.modal .modal-content .modal-body {
-ms-overflow-style: none;
scrollbar-width: none;
}
.modal .modal-content .modal-body::-webkit-scrollbar {
display: none;
}
body {
margin: 0;
background-color: #eceff1;
font-family: "Poppins", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.warning {
display: block !important;
padding: 12px 15px !important;
background-color: rgba(244, 67, 54, 0.25) !important;
border-radius: 8px !important;
font-weight: 500 !important;
color: #e53935 !important;
text-align: left !important;
}
.warning > i {
position: relative;
top: 1px;
margin-right: 8px;
transform: scale(1.25);
}
#mega-button {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
bottom: 15px;
left: 15px;
width: 50px;
height: 50px;
cursor: default;
transition: all 0.15s ease-out;
z-index: 1;
will-change: width;
}
#mega-button > .tooltip {
padding: 5px 10px;
position: absolute;
left: 10px;
top: -9px;
transform: translateY(-100%);
white-space: nowrap;
background-color: #fff;
border-radius: 8px;
filter: drop-shadow(0 2px 2px rgba(120, 144, 156, 0.5));
box-shadow: inset 0 0 0 1px rgba(120, 144, 156, 0.1);
font-weight: 500;
color: #1e4989;
-webkit-animation: tooltip-hover;
animation: tooltip-hover;
/* @keyframes duration | easing-function | delay |
iteration-count | direction | fill-mode | play-state | name */
-webkit-animation: 1s ease-in-out 0s infinite alternate both tooltip-hover;
animation: 1s ease-in-out 0s infinite alternate both tooltip-hover;
transition: all 0.15s ease-out;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
will-change: opacity;
}
#mega-button > .tooltip::before {
content: "";
display: block;
position: absolute;
bottom: 1px;
left: 8px;
width: 12px;
height: 6px;
background-color: inherit;
-webkit-clip-path: polygon(0 0, 100% 0, 50% 100%);
clip-path: polygon(0 0, 100% 0, 50% 100%);
transform: translateY(100%);
}
#mega-button::before {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 0;
top: 0;
width: 50px;
height: 50px;
padding-top: 4px;
background: 100% 100%/250% 100% #fff linear-gradient(135deg, transparent 33%, #2c92c8 66%, #892cc8) no-repeat;
border-radius: 50%;
content: "";
font-family: "Font Awesome 5 Pro";
font-size: 32px;
font-weight: 400;
color: #fff;
transition: inherit;
box-sizing: border-box;
cursor: inherit;
box-shadow: 0 10px 20px -10px #1a237e;
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
will-change: transform, background-color, box-shadow;
}
#mega-button > .sub-button {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 50%;
left: 25px;
width: 36px;
height: 36px;
background: #2c92c8;
border-radius: 50%;
text-decoration: none !important;
box-shadow: 0 10px 20px -10px #1a237e;
transform: translate(-50%, -50%) scale(0.75);
transition: inherit;
z-index: -1;
will-change: transform, transition-duration;
}
#mega-button > .sub-button::before {
font-family: "Font Awesome 5 Pro";
color: #fff;
font-size: 20px;
font-weight: 400;
transform: rotate(-90deg);
transition: inherit;
will-change: transform;
}
#mega-button > .sub-button#buttons--write::before {
content: "";
}
#mega-button > .sub-button#buttons--archive::before {
content: "";
}
#mega-button > .sub-button#buttons--delete::before {
content: "";
}
#mega-button:hover {
width: calc(50px + 2px + 123px);
}
#mega-button:hover::before {
transform: rotate(45deg) scale(0.675);
padding-right: 2px;
box-shadow: 7.5px 7.5px 20px -10px rgba(55, 71, 79, 0);
background: -100% 100%/250% 100% rgba(144, 164, 174, 0.625) linear-gradient(135deg, transparent 33%, #2c92c8 66%, #892cc8) no-repeat;
}
#mega-button:hover::after {
width: 200px;
}
#mega-button:hover > .sub-button::before {
transform: rotate(0deg);
}
#mega-button:hover > .sub-button:nth-of-type(1) {
transform: translate(calc(-50% + 50px + 0% + 0px + 2px), -50%) scale(1);
transition-delay: 0.1s;
}
#mega-button:hover > .sub-button:nth-of-type(1):hover {
transform: translate(calc(-50% + 50px + 0% + 0px + 2px), -50%) scale(1.18);
transition-duration: 0.15s;
}
#mega-button:hover > .sub-button:nth-of-type(2) {
transform: translate(calc(-50% + 50px + 100% + 5px + 2px), -50%) scale(1);
transition-delay: 0.05s;
}
#mega-button:hover > .sub-button:nth-of-type(2):hover {
transform: translate(calc(-50% + 50px + 100% + 5px + 2px), -50%) scale(1.18);
transition-duration: 0.15s;
}
#mega-button:hover > .sub-button:nth-of-type(3) {
transform: translate(calc(-50% + 50px + 200% + 10px + 2px), -50%) scale(1);
transition-delay: 0s;
}
#mega-button:hover > .sub-button:nth-of-type(3):hover {
transform: translate(calc(-50% + 50px + 200% + 10px + 2px), -50%) scale(1.18);
transition-duration: 0.15s;
}
#mega-button:hover > .sub-button:hover {
background-color: #3949ab;
}
#mega-button:hover > .sub-button:hover::before {
transform: scale(0.85);
}
#mega-button:hover .tooltip, .modal:target ~ #mega-button .tooltip {
opacity: 0;
}
.modal {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: transparent;
z-index: 2;
}
.modal > .modal-close::before {
content: "";
display: block;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
background-color: rgba(38, 50, 56, 0.5);
}
.modal .modal-content {
display: flex;
flex-direction: column;
position: fixed;
left: 50%;
top: 50%;
width: 90%;
max-width: 600px;
max-height: 90%;
overflow: visible;
transform: translate(-50%, -50%);
}
.modal .modal-content > div:first-of-type {
border-top-left-radius: 15px;
border-top-right-radius: 15px;
}
.modal .modal-content > div:last-of-type {
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
}
.modal .modal-content > .modal-close::after {
content: "";
display: flex;
align-items: center;
justify-content: center;
position: absolute;
right: 0;
top: 0;
width: 28px;
height: 28px;
z-index: -1;
background-color: #546e7a;
border-radius: 50%;
font-family: "Font Awesome 5 Pro";
font-size: 18px;
font-weight: 400;
color: #fff;
transform: translate(37.5%, -37.5%);
transition: all 0.15s ease-out;
z-index: 1;
}
.modal .modal-content > .modal-close ~ div:first-of-type {
border-top-right-radius: 0;
}
.modal .modal-content > .modal-close:hover::after {
background-color: #263238;
}
.modal .modal-content .modal-header {
padding: 10px 5px;
background-color: #37474f;
font-size: 16px;
font-weight: 600;
color: #fff;
text-transform: uppercase;
letter-spacing: 2px;
text-align: center;
}
.modal .modal-content .modal-body {
flex: 1;
display: flex;
flex-direction: column;
padding: 15px;
overflow-y: auto;
background-color: #eceff1;
}
.modal .modal-content .modal-body p {
color: #455a64;
text-align: center;
}
.modal .modal-content .modal-body p + p, .modal .modal-content .modal-body p + .modal-actions {
margin-top: 0;
}
.modal .modal-content .modal-body > :first-child {
margin-top: 0;
}
.modal .modal-content .modal-body label {
margin-bottom: 4px;
font-weight: 500;
color: #78909c;
}
.modal .modal-content .modal-body label:not(:first-of-type) {
margin-top: 10px;
}
.modal .modal-content .modal-body input, .modal .modal-content .modal-body textarea {
font-family: inherit;
}
.modal .modal-content .modal-body input:focus, .modal .modal-content .modal-body textarea:focus {
outline: 0 !important;
}
.modal .modal-content .modal-body input {
display: block;
width: 235px;
padding: 4px 10px;
align-self: flex-start;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #303f9f;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 400;
line-height: 26px;
color: #455a64;
box-sizing: border-box;
cursor: pointer;
transition: all 0.15s ease-out;
will-change: width, padding, background-color, border-radius, font-size, font-weight;
}
.modal .modal-content .modal-body input::-webkit-input-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-size: inherit;
font-weight: 500;
color: #fff;
-webkit-transition: inherit;
transition: inherit;
will-change: font-size, font-weight, color;
}
.modal .modal-content .modal-body input:-moz-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-size: inherit;
font-weight: 500;
color: #fff;
-moz-transition: inherit;
transition: inherit;
will-change: font-size, font-weight, color;
}
.modal .modal-content .modal-body input::-moz-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-size: inherit;
font-weight: 500;
color: #fff;
-moz-transition: inherit;
transition: inherit;
will-change: font-size, font-weight, color;
}
.modal .modal-content .modal-body input:-ms-input-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-size: inherit;
font-weight: 500;
color: #fff;
-ms-transition: inherit;
transition: inherit;
will-change: font-size, font-weight, color;
}
.modal .modal-content .modal-body input:focus, .modal .modal-content .modal-body input:valid {
width: 100%;
padding: 4px 0;
background-color: transparent;
border-radius: 0;
cursor: text;
}
.modal .modal-content .modal-body input:focus::-webkit-input-placeholder, .modal .modal-content .modal-body input:valid::-webkit-input-placeholder {
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body input:focus:-moz-placeholder, .modal .modal-content .modal-body input:valid:-moz-placeholder {
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body input:focus::-moz-placeholder, .modal .modal-content .modal-body input:valid::-moz-placeholder {
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body input:focus:-ms-input-placeholder, .modal .modal-content .modal-body input:valid:-ms-input-placeholder {
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body input:valid:not(:focus) {
font-size: 20px;
font-weight: 500;
}
.modal .modal-content .modal-body textarea {
display: block;
min-height: 150px;
padding: 8px 10px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
resize: vertical;
background-color: #fff;
border: none;
border-radius: 10px;
box-shadow: 0 5px 10px -5px #37474f;
font-size: 16px;
font-weight: 400;
line-height: 18px;
color: #455a64;
box-sizing: border-box;
}
.modal .modal-content .modal-body textarea::-webkit-input-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body textarea:-moz-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body textarea::-moz-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body textarea:-ms-input-placeholder {
font-family: "Font Awesome 5 Pro", "Poppins", sans-serif;
font-weight: inherit;
color: #78909c;
}
.modal .modal-content .modal-body .modal-actions {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
}
.modal .modal-content .modal-body .modal-actions a, .modal .modal-content .modal-body .modal-actions button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
display: inline-flex;
align-items: center;
justify-content: center;
height: 40px;
padding: 0 15px;
background-color: #607d8b;
border: none;
border-radius: 20px;
box-shadow: 0 5px 10px -15px #455a64;
font-family: inherit;
font-size: 16px;
font-weight: 500;
color: #fff;
text-decoration: none !important;
transition: box-shadow 0.15s ease-out;
will-change: box-shadow;
cursor: pointer;
}
.modal .modal-content .modal-body .modal-actions a.write, .modal .modal-content .modal-body .modal-actions button.write {
background-color: #2196f3;
}
.modal .modal-content .modal-body .modal-actions a.archive, .modal .modal-content .modal-body .modal-actions button.archive {
background-color: #ef6c00;
}
.modal .modal-content .modal-body .modal-actions a.delete, .modal .modal-content .modal-body .modal-actions button.delete {
background-color: #f44336;
}
.modal .modal-content .modal-body .modal-actions a.write, .modal .modal-content .modal-body .modal-actions button.write {
box-shadow: 0 5px 10px -15px #0d47a1;
}
.modal .modal-content .modal-body .modal-actions a.archive, .modal .modal-content .modal-body .modal-actions button.archive {
box-shadow: 0 5px 10px -15px #bf360c;
}
.modal .modal-content .modal-body .modal-actions a.delete, .modal .modal-content .modal-body .modal-actions button.delete {
box-shadow: 0 5px 10px -15px #b71c1c;
}
.modal .modal-content .modal-body .modal-actions a:hover, .modal .modal-content .modal-body .modal-actions button:hover {
box-shadow: 0 5px 10px -5px #455a64;
}
.modal .modal-content .modal-body .modal-actions a:hover.write, .modal .modal-content .modal-body .modal-actions button:hover.write {
box-shadow: 0 5px 10px -5px #0d47a1;
}
.modal .modal-content .modal-body .modal-actions a:hover.archive, .modal .modal-content .modal-body .modal-actions button:hover.archive {
box-shadow: 0 5px 10px -5px #bf360c;
}
.modal .modal-content .modal-body .modal-actions a:hover.delete, .modal .modal-content .modal-body .modal-actions button:hover.delete {
box-shadow: 0 5px 10px -5px #b71c1c;
}
.modal .modal-content .modal-body .modal-actions a + a, .modal .modal-content .modal-body .modal-actions a + button, .modal .modal-content .modal-body .modal-actions button + a, .modal .modal-content .modal-body .modal-actions button + button {
margin-left: 4px;
}
.modal:target {
display: block;
}
@-webkit-keyframes tooltip-hover {
from {
transform: translateY(-100%);
}
to {
transform: translateY(calc(-100% - 5px));
}
}
@keyframes tooltip-hover {
from {
transform: translateY(-100%);
}
to {
transform: translateY(calc(-100% - 5px));
}
}
<script src="https://kit.fontawesome.com/07afc061fe.js" crossorigin="anonymous"></script>
<div id="modal-write" class="modal">
<a href="#" class="modal-close"></a>
<div class="modal-content">
<a href="#" class="modal-close"></a>
<div class="modal-header">New Post</div>
<div class="modal-body">
<label for="modal-write-title">Post Title</label>
<input type="text" name="title" id="modal-write-title" placeholder=" Give your post a name..." required>
<label for="modal-write-body">Post Body</label>
<textarea name="body" cols="30" rows="10" id="modal-write-body" placeholder="What would you like to say?" required></textarea>
<div class="modal-actions">
<a href="#">Cancel</a>
<button class="write">Post</button>
</div>
</div>
</div>
</div>
<div id="modal-archive" class="modal">
<a href="#" class="modal-close"></a>
<div class="modal-content">
<a href="#" class="modal-close"></a>
<div class="modal-header">Archive Post</div>
<div class="modal-body">
<p>Would you like to archive your post?</p>
<div class="modal-actions">
<a href="#">Cancel</a>
<button class="archive">Archive</button>
</div>
</div>
</div>
</div>
<div id="modal-delete" class="modal">
<a href="#" class="modal-close"></a>
<div class="modal-content">
<a href="#" class="modal-close"></a>
<div class="modal-header">Delete Post</div>
<div class="modal-body">
<p>Are you sure you want to delete your post?</p>
<p class="warning"><i class="far fa-exclamation-circle"></i>This cannot be undone.</p>
<div class="modal-actions">
<a href="#">Cancel</a>
<button class="delete">Delete</button>
</div>
</div>
</div>
</div>
<div id="mega-button">
<div class="tooltip">Hover me!</div>
<a class="sub-button" id="buttons--write" href="#modal-write"></a>
<a class="sub-button" id="buttons--archive" href="#modal-archive"></a>
<a class="sub-button" id="buttons--delete" href="#modal-delete"></a>
</div>
Here is the finished CodePen for this solution in all its original "Sass"-y glory: https://codepen.io/brandonmcconnell/pen/082f4ee58d234501757b8d6a748c514b?editors=0100
All of the dynamic variables in this SCSS could rather simply be converted to CSS custom properties if you prefer to keep all those calculations dynamic in the final CSS.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With