Change FA Icon only with CSS - css

I have a sidebar in a project with Reactand I want that, when opening a menu item type Dropdown, the arrow changes position according to the state of the dropdown. (closed to the right, open to the bottom).
I implemented it with useState and it works without problems, depending on the statecurrent one dropdownI put one icon or another.
Question:
Can this behavior be simulated using only CSS? (I prefer to do it like this to learn on the one hand, and mainly because if I have a sidebar with 10 dropdowns or more, I will have many states and it is not the idea).
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
body {
font-family: "Lato", sans-serif;
}
/* Fixed sidenav, full height */
.sidenav {
height: 60%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}
/* Style the sidenav links and the dropdown button */
.sidenav a, .dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
</style>
</head>
<body>
<div class="sidenav">
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
</div>
<script>
/* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
</script>
</body>
</html>
I wanna change instead caret-down for caret-right onClick in the dropdown button. And if i click again, right instead down.

Fontawesome works by styling a pseudo element of an i element.
This means you can change a Fontawesome icon or you can just rotate the one that you have in CSS. For example, to have a right facing arrow instead of the down facing one next to the word Dropdown when the submenu is not dropped down and pointing down when it is, you could put this CSS in your style sheet:
.sidenav button.dropdown-btn i.fa-caret-down::before {
transform: rotate(-90deg);
display: inline-block;
}
.sidenav button.active i.fa-caret-down::before {
transform: rotate(0deg);
display: inline-block;
}
Here's the snippet
/* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
body {
font-family: "Lato", sans-serif;
}
/* Fixed sidenav, full height */
.sidenav {
height: 60%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}
/* Style the sidenav links and the dropdown button */
.sidenav a, .dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
.sidenav button.dropdown-btn i.fa-caret-down::before {
transform: rotate(-90deg);
display: inline-block;
}
.sidenav button.active i.fa-caret-down::before {
transform: rotate(0deg);
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="sidenav">
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
</div>

Related

Add Hamburger in Navigation Bar

enter image description hereI'm trying to add a hamburger slide out in my navigation bar. I would like it to slide out to the right. We're using elementor in WP. Has anyone done this before? I cannot figure out a way to do this where it will stick.
This is the code I want to use:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
function openNav() {
document.getElementById('mySidenav').style.width = '250px';
}
function closeNav() {
document.getElementById('mySidenav').style.width = '0';
}
</script>
<style>
body {
font-family: "Lato", sans-serif;
}
.elementor-menu-toggle {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
right: 0;
background-color: #f1f4ee;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.elementor-menu-toggle a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #000000;
display: block;
transition: 0.3s;
}
.elementor-menu-toggle a:hover {
color: #000000;
}
.elementor-menu-toggle .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
</style>
</head>
<body>
<div class="elementor-menu-toggle">
×
xxxxxx
xxxxxx
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
</body>
</html>
And this is what I'm getting back in the console as my class:
.elementor-84 .elementor-element.elementor-element-461994e > .elementor-widget-container {
margin: 0px 0px 0px 0px;
}
.elementor-widget-nav-menu .elementor-widget-container {
display: flex;
flex-direction: column;
}
.ob-has-background-overlay > .elementor-widget-container {
position: relative;
}
.elementor-element .elementor-widget-container {
transition: background .3s,border .3s,border-radius .3s,box-shadow .3s,transform var(--e-transform-transition-duration,.4s);
}
.elementor *, .elementor :after, .elementor :before {
box-sizing: border-box;
so I just need help figuring out which class I use, or if I'm missing something? I did try adjusting the css in the advanced widget for the nav bar, but after hitting update it does not stick.
if you are using Elementor Pro to create the header, you can use the responsive options in the advanced tab.
You could create a section only visible on desktop with the double menu and then a second section only visible in mobile with one single menu.
See more here. Responsive editing for mobile and tablets

I want to use a transition for the moment when two icons switch with each other

I'm a beginner, i searched a lot for an answer on the internet but none of them managed to clarify why the transition doesn't work.
HTML:
<li><i class="material-icons menu-bar" id="menu-bar">menu</i></li>
<ul class="menu-bar-content hide" id="menu-bar-content">
This is my Js :
const menuBar = document.getElementById('menu-bar');
const menuBarContent = document.getElementById('menu-bar-content');
var menuOpen = false;
menuBar.addEventListener('click' , menuBarBtn)
function menuBarBtn() {
if ( menuOpen == false) {
menuBar.innerHTML = '<li><i class="material-icons undo-icon">undo</i></li>';
menuBarContent.className = 'menu-bar-content';
menuOpen = true;
}
else {
menuBar.innerHTML = '<li><i class="material-icons menu-bar" id="menu-bar">menu</i></li>';
menuBarContent.className = 'menu-bar-content hide'
menuOpen = false;
}
};
And this is my Css:
.menu-bar {
display: inline-block;
vertical-align: middle;
float: right;
color: white;
margin: -1.45% 0.7%;
font-size: 23px !important;
transition: .4s;
}
.undo-icon {
display: inline-block;
vertical-align: middle;
float: right;
color: #1ec7b9;
margin: 0.9% 3%;
transform: rotateZ(43.2deg);
font-size: 14px !important;
border: 2px solid rgb(255, 255, 255);
border-radius: 70%;
padding: 1.5px;
transition: .4s;
}
After the icons switch with each other, i wanted to do it with a transition effect. Thank you in advance!
The transition is not happening because the element is completely removed/replaced with another onclick.
It is CSS properties that transition and the browser thinks it's got a completely new element, not one that is to be transitioned in some way.
What we do is have both li elements in the document all the time, but one of them will be hidden. To do this gradually we can use opacity: 0 alongside the rotation in a new class which is called faded here.
On a click we don't replace the li elements but we set the one that has not been clicked to have class faded - it will rotate and end up invisible with opacity: 0 and we remove the class faded from the other li element so it will rotate back to normal and with normal opacity.
Javascript has a handy function, toggle, for adding and removing a class so we don't have to remember which element is hidden and which is in view - having or not having class faded is enough.
Here is the snippet. Note, the body has been given a background-color just so we can see the white menu and the white border. Also I do not have access to whatever icons you are using so the i elements are replaced with spans just for this demo.
const menuBar = document.getElementById('menu-bar');
const undoBar = document.getElementById('undo-bar');
menuBar.addEventListener('click' , menuBarBtn);
undoBar.addEventListener('click' , menuBarBtn);
function menuBarBtn() {
menuBar.classList.toggle('faded');
undoBar.classList.toggle('faded');
};
body {
background-color: gray; /* just for this test so we can see the white menu */
}
.menu-bar {
display: inline-block;
vertical-align: middle;
float: right;
color: white;
margin: -1.45% 0.7%;
font-size: 23px !important;
transition: .4s;
}
.undo-icon {
display: inline-block;
vertical-align: middle;
float: right;
color: #1ec7b9;
margin: 0.9% 3%;
font-size: 14px !important;
border: 2px solid rgb(255, 255, 255);
border-radius: 70%;
padding: 1.5px;
transition: .4s;
}
.faded { /* added this so when an element has class="faded" it cannot be seen and it is rotated */
opacity: 0;
transform: rotateZ(43.2deg);
}
<ul class="menu-bar-content" id="menu-bar-content" style="margin-top:30px;"> <!-- added just for this tesmargin t so we could see the white menu word in the snippet -->
<li><span class="menu-bar" id="menu-bar">menu</span></li> <!-- remember to put back the <i icon calls in here in place of the spans -->
<li><span class="menu-bar undo-icon faded" id="undo-bar">undo</span></li> <!-- ...and we start this off as faded so it isn't seen to begin with -->
</ul>

font-awesome font prevents clickable dropdown menu from working when clicked anywhere except on the outer edge of button?

Most buttons are meant to be easily clicked. The idea of a button is to have a simple, elegant way of getting around any web-page. It is one of humanities best inventions. But I have found a way to spoil it. For some reason, by adding a font awesome icon to a downdrop button menu, It makes the whole button stop working except for on the outer corner of it. Can anyone help me make the whole button work? What is going on?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
background-color: #3498DB;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #2980B9;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd;}
.show {display: block;}
</style>
</head>
<body>
<h2>Clickable Dropdown</h2>
<p>Click on the button to open the dropdown menu.</p>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn"><i class="fa fa-list-ul fa-3x"></i></button>
<div id="myDropdown" class="dropdown-content">
Home
About
Contact
</div>
</div>
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
</body>
</html>
It turns out that the problem experienced can easily be solved. simply add a space, and then add your .dropbtn class to the icon class That is already there. Also, you will need to get rid of the fa-3x part. that is an added class member used to make the list icon bigger. but, you can also do that with a style="" that has a font-size of 3em.
When done, it should look something like this:
<i style="font-size: 3em;" class="fa fa-list-ul dropbtn"></i>

How to make CSS tooltip stay up strictly while over original item, not also over newly generated tooltip?

I only want the tooltip text to remain while the user is STRICTLY hovering over the original element, but it by default also stays while no longer hovering over the original element if the user is hovering over the tooltip text body generated by the hover. So how can (if possible) I make the tooltip text disappear once the user moves the cursor to be no longer over the original element with the hover styling even though the cursor may still be hovering over the tooltip text?
Sadly, I can't even imagine what to attempt to change this behavior so my code is exactly the same (in all relevant ways) as that provided by w3schools on how to make/use a tooltip. The code is below or you can go to their link here - https://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip
<style>
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
</style>
<body style="text-align:center;">
<p>Move the mouse over the text below:</p>
<div class="tooltip">Hover over me
<span class="tooltiptext">Tooltip text</span>
</div>
I figured it out myself!
My solution was to take care of the visibility styling with JavaScript instead of CSS so that I could have more control of conditionally rendering the tooltiptext.
I also fancied it up a little and my solution is a bit overkill because I wanted to be able to render this feature to many elements though the example here only bothers with one :)
Here's the code!
strictHoverStyle();
function strictHoverStyle(){
let overTooltipTexts = false;
let tooltipSet = document.getElementsByClassName('tooltip');
let tooltiptextSet = document.getElementsByClassName('tooltiptext');
let tooltips = Array.from(tooltipSet);
let tooltiptexts = Array.from(tooltiptextSet);
for(let i = 0; i<tooltips.length; i++){
tooltips[i].addEventListener('mouseover', function(){
if(overTooltipTexts){
tooltiptexts[i].style.visibility = 'hidden';
tooltiptexts[i].style.opacity = 'opacity 1s';
tooltiptexts[i].style.transition = 0;
} else{
tooltiptexts[i].style.visibility = 'visible';
tooltiptexts[i].style.opacity = 1;
}
});
tooltips[i].addEventListener('mouseout', function(){
tooltiptexts[i].style.visibility = "hidden";
tooltiptexts[i].style.opacity = 0;
});
tooltiptexts[i].addEventListener('mouseover', function(){
overTooltipTexts = true;
});
tooltiptexts[i].addEventListener('mouseout', function(){
overTooltipTexts = false;
});
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
top: 150%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 1s;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Strict Hover</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>
<span class="tooltip">STRICT HOVER!<span class="tooltiptext">Tooltip text</span></span>
</h1>
</body>
<script src="index.js"></script>
</html>

Inherit CSS class from separate file?

I have a class for a button:
.client-header button {
/*Properties*/
}
and a class to detect when the menu is open:
.client-menu-open {
/*Properties*/
}
I would like to change the button background based on whether or not the menu is open. I want something like this:
.client-header button .client-menu-open {
/*Properties*/
}
But the classes are in two different files, so it doesn't work. Is there any way to do this across different files?
Here is the code for the header index.css:
#import url('../menu/index.css');
.client-header {
position: absolute;
top: 0;
left: 0;
right: 0;
height: var(--header-height);
overflow: hidden;
border-bottom: 1px solid #7E7E7E;
background: #cccccc;
}
.client-header button {
float: left;
height: 100%;
border: none;
border-right: 1px solid var(--border-color);
border-radius: 0;
box-shadow: none;
line-height: 39px;
background-color: #444444;
color: #FFF;
}
.client-header button:hover {
background-color: #555555;
}
.client-header button:active {
background-color: #4E4E4E;
}
.client-header-caption {
float: left;
}
.client-header-title,
.client-header-subtitle {
margin-left: 10px;
}
.client-header-title {
line-height: 25px;
}
.client-header-subtitle {
font-size: 0.5rem;
line-height: 15px;
}
#media (min-width: 640px) {
.client-header-title,
.client-header-subtitle {
display: inline-block;
line-height: var(--header-height);
}
.client-header-title {
font-size: 1.5rem;
}
.client-header-subtitle {
font-size: 1rem;
}
}
.client-header .client-menu-open button {
background: #CCCCCC;
}
And here is the code for the menu index.css:
.client-menu {
position: absolute;
top: var(--header-height);
bottom: 0;
left: -var(--menu-width);
width: var(--menu-width);
border-right: 1px solid var(--border-color);
padding-bottom: var(--menu-footer-height);
overflow: hidden;
transition: left 0.2s;
}
.client-menu-open {
left: 0;
box-shadow: 0 0 30px var(--shadow-color);
background: #444444;
}
.client-menu-pinned {
box-shadow: none;
}
.client-menu-header {
height: var(--menu-header-height);
text-align: right;
background-color: #444444;
}
.client-menu-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: var(--menu-footer-height);
text-align: right;
}
And the HTML structure is:
<header class="client-header">
<button class="client-header-menu-toggle"/>
</header>
<div class="client-menu"/>
You can use #import like so (in your primary CSS stylesheet):
#import url('external.css');
/* external.css above will be loaded */
Refer to this documentation: http://www.cssnewbie.com/css-import-rule/
Link to the other file and style .client-menu-open
if this is your html
<div class="client-menu-open"> <!-- this class is here only if the menu gets opened, else, this div has no class -->
stuff
stuff
<div class="client-header-button">
<button></button>
</div>
</div>
the correct syntax is the following
button {
background:red;
}
.client-menu-open button {
background:blue
}
The #import rule allows you to include external style sheets in your document. It is a way of creating a style sheet within your document, and then importing additional rules into the document.
To use the #import rule, type:
<style type="text/css">
#import url("import1.css");
#import url "import2.css";
</style>
For more info refer here https://developer.mozilla.org/en-US/docs/Web/CSS/#import
your CSS selector is incorrect, that's why it doesn't work. It has nothing to do with where CSS styles are defined.
.client-header button .client-menu-open will only select the following elements:
elements with class="client-menu-open"
which are children of button elements
which themselves are children of elements with class="client-header"
.
what you want, I think, is
button elements
which are children of elements having "class=client-header" AND "class=client-menu-open".
the proper selector for those elements would be .client-header.client-menu-open button.

Resources