I have created a vertical menu and I want to expand it over the entire height of the viewport but if this is not sufficient to contain it I would like some scroll mechanism (on the page or on the vertical menu it is fine in both cases) that allows me to do so. I've tried several ways but I can't get the desired effect.
With this solution header.sidebar
is position:sticky
and I can see all the vertical menu when I scroll on the body, but only when I have scrolled a lot and this isn't user friendly. This isn't acceptable.
/*#region BASE */
@import url("https://fonts.googleapis.com/css2?family=Anta&family=Madimi+One&display=swap");
*,
*::after,
*::before {
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
font-family: inherit;
}
html {
font-size: 16px;
}
body {
background-image: url("https://i.ibb.co/gDgZ3c9/background-Template.png");
background-size: cover;
background-attachment: fixed;
font-family: "Anta", sans-serif;
/* Non uso gridbox perchè gridbox imposta la dimensione delle colonne nell'elemento genitore(quindi qui nel body) con la
proprietà grid-template-columns e non riuscirei con il meccanismo dell'input:checkbox a cambiarne la dimensione
(perchè non posso selezionare il body quando l'input è checked perchè il body è l'elemento genitore).
Con flexbox invece quando clicco sull'hamburger menu basta cambiare la dimensione della sidebar */
display: flex;
/* Questa serve affinchè */
align-items: start;
}
a {
text-decoration: none;
}
/*#endregion BASE */
/*#region SIDEBAR*/
/* Uso position:sticky e top:0 left:0 perchè non voglio */
header.sidebar {
position: sticky;
/* overflow-y: auto;
overflow-x: visible; */
top: 0;
bottom: 0;
left: 0;
background-image: linear-gradient(
30deg,
rgba(5, 5, 75, 0.85),
rgba(5, 5, 75, 0.85) 20%,
rgb(5, 5, 75)
);
min-height: 100vh;
min-height: 100svh;
width: 65px;
padding: 0.4rem 0.8rem;
transition: all 0.5s ease;
}
/*#region SIDEBAR HEADER*/
.sidebar__header {
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__header__logo {
display: flex;
align-items: center;
display: none;
}
.sidebar__header__logo img {
width: 50px;
}
.sidebar__header__logo span {
color: white;
}
.sidebar__header__hamburger {
cursor: col-resize;
margin-top: 0.4rem;
}
/*#endregion SIDEBAR HEADER*/
/*#region SIDEBAR USER*/
.sidebar__user {
display: flex;
justify-content: center;
}
.sidebar__user__img {
width: 50px;
height: 50px;
object-fit: cover;
border: 3px solid rgb(182, 5, 152);
border-top-color: rgb(23, 23, 201);
border-bottom-color: rgb(23, 23, 201);
border-radius: 50%;
margin-top: 20px;
}
.sidebar__user__name {
display: none;
}
/*#endregion SIDEBAR USER*/
/*#region SIDEBAR MENU*/
.sidebar__menu__item {
min-height: 40px;
margin: 10px 0;
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__menu__item:hover {
border-radius: 10px;
background-color: white;
}
.sidebar__menu__item:hover .sidebar__menu__item__icon::before {
/* background-image: red; */
background-image: linear-gradient(rgb(5, 5, 75), rgb(5, 5, 75));
font-size: larger;
}
.sidebar__menu__item a {
position: relative; /* Serve per posizionare il tooltip */
display: block;
/* Le seguenti due regole servono per far si che il
tag a si sovrapponga perfettamente all'li
genitore in modo che la superficie cliccabile
del link cresca e sia uguale a quella dell'li */
width: 100%;
min-height: inherit;
display: flex;
justify-content: center;
align-items: center;
}
.sidebar__menu__item__text {
height: 3.2em;
min-width: 100px;
display: none;
font-size: 1rem;
background-color: rgb(182, 5, 152);
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Questa regola funge da fallback in caso -webkit-text-fill-color o background-clip: text;
non siano supportati */
.sidebar__menu__item__icon {
color: rgb(23, 23, 201);
}
:is(.sidebar__menu__item__icon, .sidebar__header__hamburger)::before {
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
.sidebar__menu__tooltip {
position: absolute;
right: 0;
top: 50%;
/* 0.8rem è la dimensione del padding destro della sidebar */
/* 10px è la distanza con cui voglio distanziare il
tooltip dal bordo della sidebar */
transform: translate(calc(100% + 0.8rem + 10px), -50%);
background-color: white;
border-radius: 8px;
min-width: 75px;
text-align: center;
font-size: 0.7rem;
font-weight: 500;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
padding: 5px;
letter-spacing: -0.2px;
display: none;
color: rgb(5, 5, 75);
}
.sidebar__menu__item a:hover .sidebar__menu__tooltip {
display: block;
}
/*#endregion SIDEBAR MENU*/
/*#region SIDEBAR INPUT*/
input#sidebar-toggle {
display: none;
}
input#sidebar-toggle:checked + header.sidebar {
width: 250px;
}
/*#endregion SIDEBAR INPUT*/
/*#endregion SIDEBAR*/
/*#region MAIN */
/* input#sidebar-toggle:checked ~ main.main-content {
} */
main.main-content {
flex-grow: 1;
}
/*#endregion MAIN */
/* per i devices che non supportano l'hover aggiungo il focus e l'active per intercettare il touch.
In questo modo avrò la comparsa del tooltip al touch (long touch).
Così più che realizzare l'hover ho realizzato il click ma mi sta bene
Questa soluzione potrebbe non funzionare per i browser mobile Edge per i quali devi aggiungere nell'html
aria-haspopup="true" */
/* In questo caso la media query @media all and (hover: none) serve perchè altrimenti se tieni premuto
una voce di menu si attiva il popup e rimane aperto (perchè è active) e rimarrà aperto finchè non cliccki altrove.
Per capirlo prova il codice su un computer con mouse rimuovendo la media query @media all and (hover: none)
Nota che stiamo trascurando altri dispositivi di puntamento (come i pennini)
*/
@media all and (hover: none) {
.sidebar__menu__item a:focus .sidebar__menu__tooltip,
.sidebar__menu__item a:active .sidebar__menu__tooltip {
background-color: red;
display: block;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dashboard</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA=="
crossorigin="anonymous" />
<link rel="stylesheet" href="../css/dashboard.css" />
<script src="../js/dashboard.js" defer></script>
</head>
<body>
<input type="checkbox" name="sidebar-toggle" id="sidebar-toggle" />
<header class="sidebar">
<div class="sidebar__header">
<div class="sidebar__header__logo">
<!-- <i class="fa-brands fa-codepen"></i> -->
<img src="../../assets/img/logo.png" alt="" />
<span>Wardiere</span>
</div>
<label for="sidebar-toggle">
<i class="fa-solid fa-bars sidebar__header__hamburger"></i>
</label>
</div>
<div class="sidebar__user">
<img src="https://i.ibb.co/tP3Vryt/foto.jpg"
class="sidebar__user__img" alt="foto profilo" >
<p class="sidebar__user__name">Marco Rossi</p>
</div>
<nav class="sidebar__menu">
<ul>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-window-maximize fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Dashboard</span>
<span class="sidebar__menu__tooltip">Dashboard</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-message fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Messages</span>
<span class="sidebar__menu__tooltip">Messages</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-dollar-sign fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Revenue</span>
<span class="sidebar__menu__tooltip">Revenue</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-bell fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Notifications</span>
<span class="sidebar__menu__tooltip">Notifications</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-heart fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Likes</span>
<span class="sidebar__menu__tooltip">Likes</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-wallet fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Wallet</span>
<span class="sidebar__menu__tooltip">Wallet</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-gear fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Settings</span>
<span class="sidebar__menu__tooltip">Settings</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="../../index.html">
<i class="fa-solid fa-house fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Home</span>
<span class="sidebar__menu__tooltip">Home</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main-content" style="margin-top: 2000px">
<h1 style="color: red">DASHBOARD</h1>
</main>
<script defer src="../js/dashboard.js"></script>
</body>
</html>
With this more canonical solution:
/*#region BASE */
@import url("https://fonts.googleapis.com/css2?family=Anta&family=Madimi+One&display=swap");
*,
*::after,
*::before {
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
font-family: inherit;
}
html {
font-size: 16px;
}
body {
background-image: url("https://i.ibb.co/gDgZ3c9/background-Template.png");
background-size: cover;
background-attachment: fixed;
font-family: "Anta", sans-serif;
/* Non uso gridbox perchè gridbox imposta la dimensione delle colonne nell'elemento genitore(quindi qui nel body) con la
proprietà grid-template-columns e non riuscirei con il meccanismo dell'input:checkbox a cambiarne la dimensione
(perchè non posso selezionare il body quando l'input è checked perchè il body è l'elemento genitore).
Con flexbox invece quando clicco sull'hamburger menu basta cambiare la dimensione della sidebar */
display: flex;
/* Questa serve affinchè */
align-items: start;
}
a {
text-decoration: none;
}
/*#endregion BASE */
/*#region SIDEBAR*/
/* Uso position:sticky e top:0 left:0 perchè non voglio */
header.sidebar {
position: fixed;
overflow-y: auto;
overflow-x: visible;
top: 0;
bottom: 0;
left: 0;
background-image: linear-gradient(
30deg,
rgba(5, 5, 75, 0.85),
rgba(5, 5, 75, 0.85) 20%,
rgb(5, 5, 75)
);
height: 100vh;
height: 100svh;
width: 65px;
padding: 0.4rem 0.8rem;
transition: all 0.5s ease;
}
/*#region SIDEBAR HEADER*/
.sidebar__header {
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__header__logo {
display: flex;
align-items: center;
display: none;
}
.sidebar__header__logo img {
width: 50px;
}
.sidebar__header__logo span {
color: white;
}
.sidebar__header__hamburger {
cursor: col-resize;
margin-top: 0.4rem;
}
/*#endregion SIDEBAR HEADER*/
/*#region SIDEBAR USER*/
.sidebar__user {
display: flex;
justify-content: center;
}
.sidebar__user__img {
width: 50px;
height: 50px;
object-fit: cover;
border: 3px solid rgb(182, 5, 152);
border-top-color: rgb(23, 23, 201);
border-bottom-color: rgb(23, 23, 201);
border-radius: 50%;
margin-top: 20px;
}
.sidebar__user__name {
display: none;
}
/*#endregion SIDEBAR USER*/
/*#region SIDEBAR MENU*/
.sidebar__menu__item {
min-height: 40px;
margin: 10px 0;
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__menu__item:hover {
border-radius: 10px;
background-color: white;
}
.sidebar__menu__item:hover .sidebar__menu__item__icon::before {
/* background-image: red; */
background-image: linear-gradient(rgb(5, 5, 75), rgb(5, 5, 75));
font-size: larger;
}
.sidebar__menu__item a {
position: relative; /* Serve per posizionare il tooltip */
display: block;
/* Le seguenti due regole servono per far si che il
tag a si sovrapponga perfettamente all'li
genitore in modo che la superficie cliccabile
del link cresca e sia uguale a quella dell'li */
width: 100%;
min-height: inherit;
display: flex;
justify-content: center;
align-items: center;
}
.sidebar__menu__item__text {
height: 3.2em;
min-width: 100px;
display: none;
font-size: 1rem;
background-color: rgb(182, 5, 152);
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Questa regola funge da fallback in caso -webkit-text-fill-color o background-clip: text;
non siano supportati */
.sidebar__menu__item__icon {
color: rgb(23, 23, 201);
}
:is(.sidebar__menu__item__icon, .sidebar__header__hamburger)::before {
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
.sidebar__menu__tooltip {
position: absolute;
right: 0;
top: 50%;
/* 0.8rem è la dimensione del padding destro della sidebar */
/* 10px è la distanza con cui voglio distanziare il
tooltip dal bordo della sidebar */
transform: translate(calc(100% + 0.8rem + 10px), -50%);
background-color: white;
border-radius: 8px;
min-width: 75px;
text-align: center;
font-size: 0.7rem;
font-weight: 500;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
padding: 5px;
letter-spacing: -0.2px;
display: none;
color: rgb(5, 5, 75);
}
.sidebar__menu__item a:hover .sidebar__menu__tooltip {
display: block;
}
/*#endregion SIDEBAR MENU*/
/*#region SIDEBAR INPUT*/
input#sidebar-toggle {
display: none;
}
input#sidebar-toggle:checked + header.sidebar {
width: 250px;
}
/*#endregion SIDEBAR INPUT*/
/*#endregion SIDEBAR*/
/*#region MAIN */
/* input#sidebar-toggle:checked ~ main.main-content {
} */
main.main-content {
flex-grow: 1;
}
/*#endregion MAIN */
/* per i devices che non supportano l'hover aggiungo il focus e l'active per intercettare il touch.
In questo modo avrò la comparsa del tooltip al touch (long touch).
Così più che realizzare l'hover ho realizzato il click ma mi sta bene
Questa soluzione potrebbe non funzionare per i browser mobile Edge per i quali devi aggiungere nell'html
aria-haspopup="true" */
/* In questo caso la media query @media all and (hover: none) serve perchè altrimenti se tieni premuto
una voce di menu si attiva il popup e rimane aperto (perchè è active) e rimarrà aperto finchè non cliccki altrove.
Per capirlo prova il codice su un computer con mouse rimuovendo la media query @media all and (hover: none)
Nota che stiamo trascurando altri dispositivi di puntamento (come i pennini)
*/
@media all and (hover: none) {
.sidebar__menu__item a:focus .sidebar__menu__tooltip,
.sidebar__menu__item a:active .sidebar__menu__tooltip {
background-color: red;
display: block;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dashboard</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA=="
crossorigin="anonymous" />
<link rel="stylesheet" href="../css/dashboard.css" />
<script src="../js/dashboard.js" defer></script>
</head>
<body>
<input type="checkbox" name="sidebar-toggle" id="sidebar-toggle" />
<header class="sidebar">
<div class="sidebar__header">
<div class="sidebar__header__logo">
<!-- <i class="fa-brands fa-codepen"></i> -->
<img src="../../assets/img/logo.png" alt="" />
<span>Wardiere</span>
</div>
<label for="sidebar-toggle">
<i class="fa-solid fa-bars sidebar__header__hamburger"></i>
</label>
</div>
<div class="sidebar__user">
<img
src="https://i.ibb.co/tP3Vryt/foto.jpg"
class="sidebar__user__img"
alt="foto profilo" />
<p class="sidebar__user__name">Marco Rossi</p>
</div>
<nav class="sidebar__menu">
<ul>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-window-maximize fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Dashboard</span>
<span class="sidebar__menu__tooltip">Dashboard</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-message fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Messages</span>
<span class="sidebar__menu__tooltip">Messages</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-dollar-sign fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Revenue</span>
<span class="sidebar__menu__tooltip">Revenue</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-bell fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Notifications</span>
<span class="sidebar__menu__tooltip">Notifications</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-heart fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Likes</span>
<span class="sidebar__menu__tooltip">Likes</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-wallet fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Wallet</span>
<span class="sidebar__menu__tooltip">Wallet</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i class="fa-solid fa-gear fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Settings</span>
<span class="sidebar__menu__tooltip">Settings</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="../../index.html">
<i class="fa-solid fa-house fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Home</span>
<span class="sidebar__menu__tooltip">Home</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main-content" style="margin-top: 2000px">
<h1 style="color: red">DASHBOARD</h1>
</main>
<script defer src="../js/dashboard.js"></script>
</body>
</html>
I have (with position:fixed
and overflow-y:auto
and overflow-x:visible
) the vertical scrollbar on my vertical menu however I have an horizontal scrollbar too. I could hide it with overflow-x:hidden
but in this way the tooltip that appears (on the right side of vertical menu) on :hover
on an item menu isn't visible anymore. Instead with the horizontal scrollbar visible (without overflow-x:hidden
) this tooltip is inglobated inside the sidebar menu and visible only with horizontal scroll.
This make me crazy. How could I resolve?
const ulInsideNav = document.querySelector(".sidebar__menu > ul");
//uso anche il touch e non solo l'hover per supportare anche il mobile.
//Uso event delegation
ulInsideNav.addEventListener("mouseover", displayTooltip);
ulInsideNav.addEventListener("touch", displayTooltip);
function displayTooltip(e) {
if (e.type === "touch") {
//dopo l'evento touch potrebbe essere innescato anche l'hover e quindi per
//evitare due volte l'esecuzione uso preventDefault
e.preventDefault();
}
let elClicked = e.target;
let elClickedType = e.target.tagName.toLowerCase();
//Se ho cliccato sul tag i(l'icona font-awesome) mi faccio tornare il tag a genitore
if (elClickedType === "i") {
elClicked = elClicked.parentElement;
elClickedType = "a";
}
//Mi assicuro che il click sia avvenuto su un tag a (se è avvenuto sul tag i ho già provveduto a farmi tornare il tag a genitore)
if (elClickedType === "a") {
const iconTooltip = elClicked.querySelector(".sidebar__menu__tooltip");
const sidebarWrapper = document.querySelector(".sidebar--wrapper");
const sidebar = document.querySelector(".sidebar");
iconTooltip.style.cssText = `
top:${
elClicked.offsetTop +
Math.round(elClicked.offsetHeight) / 2 -
Math.round(iconTooltip.offsetHeight) / 2 -
sidebar.scrollTop +
"px"
};
left: ${Math.round(sidebarWrapper.offsetWidth + 10) + "px"};
`;
//Quando perdi l'hover non c'è bisogno di togliere lo stile inline perchè perdendo l'hover
//il tooltip ha il display:none
}
}
/*#region BASE */
@import url("https://fonts.googleapis.com/css2?family=Anta&family=Madimi+One&display=swap");
*,
*::after,
*::before {
margin: 0;
padding: 0;
list-style: none;
box-sizing: border-box;
font-family: inherit;
}
:root {
font-size: 16px;
}
body {
background-image: url("https://i.ibb.co/gDgZ3c9/background-Template.png");
background-size: cover;
background-attachment: fixed;
font-family: "Anta", sans-serif;
/* Non uso gridbox perchè gridbox imposta la dimensione delle colonne nell'elemento genitore(quindi qui nel body) con la
proprietà grid-template-columns e non riuscirei con il meccanismo dell'input:checkbox a cambiarne la dimensione
(perchè non posso selezionare il body quando l'input è checked perchè il body è l'elemento genitore).
Con flexbox invece quando clicco sull'hamburger menu basta cambiare la dimensione della sidebar */
display: flex;
/* Questa serve affinchè */
align-items: start;
}
a {
text-decoration: none;
}
/*#region SCROLLBAR*/
/* Il predisso webkit è per browser come Safari Chrome
ed Edge. Tuttavia queste regole non funzioneranno
per Firefox per il quale possiamo usare
scrollbar-color: hsl(240, 78%, 50%) hsl(240, 88%, 86%);
scrollbar-width: auto;
Tuttavia queste due sono supportate anche da
Chrome e altri browser e andrebbero a sovrascrivere
le regole date con ::-webkit
per cui utilizzo @supports
@supports not (selector(::-webkit-scrollbar))
Cioè se non supporto -webkit-scrollbar (e se
non lo supporto non saranno supportate neanche le
altre proprità allora attivo la fallback).
Nota che uso il not e selector() perchè
::-webkit-scrollbar non è una proprietà
ma un selettore. */
::-webkit-scrollbar {
width: 12px;
height: 12px;
}
/* Larghezza della scrollbar nel body */
.sidebar::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: hsl(240, 88%, 86%);
border-radius: 100vw;
/* margin-block di default definisce il margin-top e il margin-bottom */
margin-block: 1px;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(hsl(240, 78%, 50%), hsl(289, 88%, 33%));
border: 2px solid hsl(289, 88%, 83%);
border-radius: 100vw;
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(hsl(240, 88%, 20%), hsl(289, 98%, 23%));
}
@supports not (selector(::-webkit-scrollbar)) {
* {
scrollbar-color: hsl(240, 78%, 50%) hsl(240, 88%, 86%);
scrollbar-width: auto; /* auto none thin */
}
}
/* @supports (scrollbar-color: hsl(240, 78%, 50%) hsl(240, 88%, 86%)) {
* {
scrollbar-color: hsl(240, 78%, 50%) hsl(240, 88%, 86%);
scrollbar-width: auto;
}
} */
/*#endregion SCROLLBAR*/
/*#endregion BASE */
/*#region SIDEBAR*/
/* Uso position:sticky e top:0 left:0 perchè non voglio */
.sidebar--wrapper {
position: fixed;
top: 0;
bottom: 0;
left: 0;
/* min-height: 100vh;
min-height: 100svh; */
width: 68px;
transition: width 0.35s;
}
header.sidebar {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
background-image: linear-gradient(
30deg,
rgba(5, 5, 75, 0.85),
rgba(5, 5, 75, 0.85) 20%,
rgb(5, 5, 75)
);
padding: 0.4rem 0.8rem;
transition: all 0.5s ease;
}
/*#region SIDEBAR HEADER*/
.sidebar__header {
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__header__logo {
display: flex;
align-items: center;
display: none;
}
.sidebar__header__logo img {
width: 50px;
}
.sidebar__header__logo span {
color: white;
}
[for="sidebar-toggle"] {
display: none;
}
.sidebar__header__hamburger {
cursor: col-resize;
margin-top: 0.4rem;
}
/*#endregion SIDEBAR HEADER*/
/*#region SIDEBAR USER*/
.sidebar__user {
display: flex;
justify-content: center;
}
.sidebar__user__img {
width: 50px;
height: 50px;
object-fit: cover;
border: 3px solid rgb(182, 5, 152);
border-top-color: rgb(23, 23, 201);
border-bottom-color: rgb(23, 23, 201);
border-radius: 50%;
margin-top: 20px;
}
.sidebar__user__name {
display: none;
}
/*#endregion SIDEBAR USER*/
/*#region SIDEBAR MENU*/
.sidebar__menu__item {
min-height: 40px;
margin: 10px 0;
display: flex;
align-items: center;
justify-content: center;
}
.sidebar__menu__item:hover {
border-radius: 10px;
background-color: white;
}
/* L'icona rispetto al tag a è più in basso nel markup quindi sta davanti e quindi quando ci vai con
il mouse sopra tanti eventi mouseover sono innescati passando dal tag a all'icona (tag i), per
motivi di efficienza cioè per evitare di chiamare più volte il gestore di evento del mouse
ho messo il pointer-events:none sul tag i(icona) */
.sidebar__menu__item__icon {
pointer-events: none;
}
.sidebar__menu__item:hover .sidebar__menu__item__icon::before {
/* background-image: red; */
background-image: linear-gradient(rgb(5, 5, 75), rgb(5, 5, 75));
font-size: larger;
}
.sidebar__menu__item a {
/* position: relative; */ /* Serve per posizionare il tooltip */
display: block;
/* Le seguenti due regole servono per far si che il
tag a si sovrapponga perfettamente all'li
genitore in modo che la superficie cliccabile
del link cresca e sia uguale a quella dell'li */
width: 100%;
min-height: inherit;
display: flex;
justify-content: center;
align-items: center;
}
.sidebar__menu__item__text {
height: 3.2em;
min-width: 100px;
display: none;
font-size: 1rem;
background-color: rgb(182, 5, 152);
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Nota che per background-clip c'è un bug noto quando lo
usi */
:is(.sidebar__menu__item__icon, .sidebar__header__hamburger)::before {
background-image: linear-gradient(
to right,
rgb(23, 23, 201),
rgb(182, 5, 152)
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Questa regola funge da fallback in caso -webkit-text-fill-color o background-clip: text;
non siano supportati. Ad esempio in Opera senza
queste regole non riuscirei a vedere le icone */
@supports not (
(background-clip: text) and (-webkit-text-fill-color: transparent)
) {
:is(.sidebar__menu__item__icon, .sidebar__header__hamburger)::before {
-webkit-text-fill-color: unset;
background-image: none;
background-clip: unset;
color: rgb(23, 23, 201);
}
.sidebar__menu__item__text {
-webkit-text-fill-color: unset;
background-image: none;
background-clip: unset;
color: rgb(23, 23, 201);
}
.sidebar__menu__item:hover .sidebar__menu__item__icon::before {
background-image: none;
}
}
.sidebar__menu__tooltip {
position: absolute;
/* right: 0;
top: 50%; */
/* 0.8rem è la dimensione del padding destro della sidebar */
/* 10px è la distanza con cui voglio distanziare il
tooltip dal bordo della sidebar */
/* transform: translate(calc(100% + 0.8rem + 10px), -50%); */
background-color: white;
border-radius: 8px;
min-width: 75px;
text-align: center;
font-size: 0.7rem;
font-weight: 500;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
padding: 5px;
letter-spacing: -0.2px;
display: none;
color: rgb(5, 5, 75);
}
.sidebar__menu__item a:hover .sidebar__menu__tooltip {
display: block;
}
/*#endregion SIDEBAR MENU*/
/*#region SIDEBAR INPUT*/
input#sidebar-toggle {
display: none;
}
input#sidebar-toggle:checked ~ main.main-content {
margin-left: 250px;
}
/*#endregion SIDEBAR INPUT*/
/*#endregion SIDEBAR*/
/*#region MAIN */
/* input#sidebar-toggle:checked ~ main.main-content {
} */
main.main-content {
flex-grow: 1;
margin-left: 68px;
}
/*#endregion MAIN */
/* per i devices che non supportano l'hover aggiungo il focus e l'active per intercettare il touch.
In questo modo avrò la comparsa del tooltip al touch (long touch).
Così più che realizzare l'hover ho realizzato il click ma mi sta bene
Questa soluzione potrebbe non funzionare per i browser mobile Edge per i quali devi aggiungere nell'html
aria-haspopup="true" */
/* In questo caso la media query @media all and (hover: none) serve perchè altrimenti se tieni premuto
una voce di menu si attiva il popup e rimane aperto (perchè è active) e rimarrà aperto finchè non cliccki altrove.
Per capirlo prova il codice su un computer con mouse rimuovendo la media query @media all and (hover: none)
Nota che stiamo trascurando altri dispositivi di puntamento (come i pennini)
*/
@media all and (hover: none) {
.sidebar__menu__item a:focus .sidebar__menu__tooltip,
.sidebar__menu__item a:active .sidebar__menu__tooltip {
/* background-color: red; */
display: block;
}
}
@media all and (min-width: 600px) {
[for="sidebar-toggle"] {
display: block;
}
/* Questa regola dice che se il menu è espanso il tooltip non lo si deve vedere
e siccome può essere espanso solo sopra il breakpoint corrente è idoneo mettere
questa regola in questa media query
*/
input#sidebar-toggle:checked
+ .sidebar--wrapper
.sidebar__menu__item
a:hover
.sidebar__menu__tooltip {
display: none;
}
/* Devo consentire di espandere il menu a 250px solo oltre il breakpoint prescelto corrente
quindi anche questa regola va inserita qui */
input#sidebar-toggle:checked + .sidebar--wrapper {
width: 250px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dashboard</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA=="
crossorigin="anonymous" />
<link rel="stylesheet" href="./b.css" />
</head>
<body>
<input type="checkbox" name="sidebar-toggle" id="sidebar-toggle" />
<!-- Ad [1] in fondo alla pagina spiego il perchè serve questo wrapper -->
<div class="sidebar--wrapper">
<header class="sidebar">
<div class="sidebar__header">
<div class="sidebar__header__logo">
<!-- <i class="fa-brands fa-codepen"></i> -->
<img src="../../assets/img/logo.png" alt="" />
<span>Wardiere</span>
</div>
<label for="sidebar-toggle">
<i class="fa-solid fa-bars sidebar__header__hamburger"></i>
</label>
</div>
<div class="sidebar__user">
<img
src="https://i.ibb.co/tP3Vryt/foto.jpg"
class="sidebar__user__img"
alt="foto profilo" />
<p class="sidebar__user__name">Marco Rossi</p>
</div>
<nav class="sidebar__menu">
<ul>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-window-maximize fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Dashboard</span>
<span class="sidebar__menu__tooltip">Dashboard</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-message fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Messages</span>
<span class="sidebar__menu__tooltip">Messages</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-dollar-sign fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Revenue</span>
<span class="sidebar__menu__tooltip">Revenue</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-bell fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Notifications</span>
<span class="sidebar__menu__tooltip">Notifications</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-heart fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Likes</span>
<span class="sidebar__menu__tooltip">Likes</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-wallet fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Wallet</span>
<span class="sidebar__menu__tooltip">Wallet</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="#">
<i
class="fa-solid fa-gear fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Settings</span>
<span class="sidebar__menu__tooltip">Settings</span>
</a>
</li>
<li class="sidebar__menu__item">
<a href="../../index.html">
<i
class="fa-solid fa-house fa-2xs sidebar__menu__item__icon"></i>
<span class="sidebar__menu__item__text">Home</span>
<span class="sidebar__menu__tooltip">Home</span>
</a>
</li>
</ul>
</nav>
</header>
</div>
<main class="main-content" style="margin-top: 2000px">
<h1 style="color: red">DASHBOARD</h1>
</main>
<script src="./c.js"></script>
</body>
</html>
<!-- [1] Se l'altezza della viewport del browser non riesce a contenere tutti gli
elementi nella sidebar viene introdotta automaticamente una barra di scorrimento
alla pagina. Tuttavia se poi nel tag main ho più contenuto rispetto alla sidebar
avrò una sidebar più corta rispetto al tag main affianco che è brutto da vedere.
Allora fisso l'altezza della sidebar (con position:fixed ed
height:100vh) in modo che scrollando la pagina la sidebar rimane fissa a
sinistra. Però in questo modo se l'altezza della viewport è piccola rischio di
non vedere più la parte finale della sidebar e voglio che sulla sidebar venga
introdotta la barra di scorrimento (non alla pagina, ma proprio alla sidebar). E
questo è facile da fare, basta dare overflow-y:auto. Però in questo modo non
riesco più a vedere i tooltip (che sono un overflow orizzontale) quando vado con
il mouse sopra alle icone. Mettendo overflow-x:visible non funziona. Siamo
incappati in uno di quei comportamenti stranissimi del css che lo fanno odiare.
Se setti l'overflow in una direzione ad auto nell'altra direzione anche se lo
setti a visible sarà comunque auto e quindi compare una barra di scorrimento
orizzontale e il tooltip non lo vedi più se non scorrendo orizzontalmente Il
tutto è documentato qui
https://css--tricks-com.translate.goog/popping-hidden-overflow/?_x_tr_sl=en&_x_tr_tl=it&_x_tr_hl=it&_x_tr_pto=sc
AL link che ti ho messo c'è anche la soluzione che richiede anche l'intervento
di javascript e una modifica al css e all'html. Alla sidebar possiamo dare
overflow-y:auto e overflow-x:hidden. E ora il tooltip come lo vedo dato che
overflow-x:hidden? Grazie a un meccanismo particolare di css:
Se voglio vedere un elemento contenuto dentro un elemento con overflow:hidden all'elemento che voglio vedere posso
dare position:absolute o position:relative e poi il suo antenato più vicino con position diverso da static deve
essere anche un antenato dell'elemento con position:hidden.
Nel nostro caso il tooltip ha un genitore (il tag a) con il position relative (e il tag a non è un antenato della sidebar)
quindi dobbiamo togliere il position:relative al tag a .
Mettiamo la sidebar dentro un elemento wrapper (quello con classe .sidebar-wrapper) al quale daremo position:fixed
e vedremo i nostri tooltip fuori dalla sidebar all'hover. Tuttavia i tooltip con top,left ecc. saranno posizionati
rispetto alla sidebar e non rispetto al link. Ed a questo punto subentra javascript.
Nota che il gestore di evento javascript al mouseover mi serve solo se c'è un overflow verticale della sidebar.
Potrei quindi rilevare tramite js se non c'è overflow verticale e in tal caso togliere i gestori di evento del mouse
(e gestire tramite css la centratura) e viceversa. Ma sarebbe un complicarsi le cose senza nessun grande guadagno.
-->
Above the solution: This was a problem that I had already tackled and I had forgot: My explication of the above solution is: If the height of the browser viewport cannot contain all the elements in the sidebar, a scroll bar is automatically introduced to the page. However, if the main tag contains more content than the sidebar, the sidebar will be shorter than the main tag next to it, which looks bad. So, I fix the height of the sidebar (with position:fixed and height:100vh) so that when scrolling the page, the sidebar remains fixed on the left. However, this way, if the viewport height is small, I risk not seeing the final part of the sidebar, and I want a scroll bar to be introduced on the sidebar itself (not on the page, but directly on the sidebar). And this is easy to do, just by giving overflow-y:auto. However, this way, I can no longer see the tooltips (which are a horizontal overflow) when I hover over the icons. Setting overflow-x:visible doesn't work. We've encountered one of those very strange CSS behaviors that make it hated. If you set overflow in one direction to auto, in the other direction, even if you set it to visible, it will still be auto, so a horizontal scroll bar appears, and you no longer see the tooltip unless you scroll horizontally. It's all documented here: CSS-Tricks.
At the link I provided, there is also a solution that requires the intervention of JavaScript and a modification to the CSS and HTML. We can give overflow-y:auto and overflow-x:hidden to the sidebar. Now, how do I see the tooltip since overflow-x:hidden? Thanks to a particular CSS mechanism:
If I want to see an element contained within an element with overflow:hidden, I can give position:absolute or position:relative to the element I want to see, and then its nearest ancestor with a position other than static must also be an ancestor of the element with position:hidden. In our case, the tooltip has a parent (the 'a' tag) with relative position (and the 'a' tag is not an ancestor of the sidebar), so we need to remove position:relative from the 'a' tag. We put the sidebar inside a wrapper element (the one with class .sidebar-wrapper) to which we will give position:fixed, and we will see our tooltips outside the sidebar on hover. However, tooltips with top, left, etc. will be positioned relative to the sidebar and not to the link. At this point, JavaScript comes in.
Note that the JavaScript event handler for mouseover is only needed if there is a vertical overflow of the sidebar. So, I could detect via JS if there is no vertical overflow and in that case remove the mouse event handlers (and manage centering via CSS) and vice versa. But it would complicate things without any great benefit.