aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-11-13 20:19:48 +0100
committerpolo <ordipolo@gmx.fr>2025-11-13 20:19:48 +0100
commitd52afe5cc37ce1e88772e7cb7a40b54bbbebda83 (patch)
treece7fbb8109794c5a9d3c88a88a7dfd8db28c2023
parent9e28a093480220d63960a4431c2decc354a7c7ca (diff)
downloadcms-d52afe5cc37ce1e88772e7cb7a40b54bbbebda83.tar.gz
cms-d52afe5cc37ce1e88772e7cb7a40b54bbbebda83.tar.bz2
cms-d52afe5cc37ce1e88772e7cb7a40b54bbbebda83.zip
classe CSS drop-left pour ouvrir des sous-menus à gauche, normes de responsive design: 480, 768 et 1024px
-rw-r--r--public/css/head.css23
-rw-r--r--public/css/nav.css85
-rw-r--r--public/js/main.js27
3 files changed, 87 insertions, 48 deletions
diff --git a/public/css/head.css b/public/css/head.css
index 4df68ba..b5acfec 100644
--- a/public/css/head.css
+++ b/public/css/head.css
@@ -47,7 +47,7 @@ header h2
47 font-size: medium; /* défaut = x-large */ 47 font-size: medium; /* défaut = x-large */
48 margin: 10px; 48 margin: 10px;
49} 49}
50@media screen and (max-width: 1000px){ 50@media screen and (max-width: 1024px){
51 header h1, header h2 51 header h1, header h2
52 { 52 {
53 margin: 8px; 53 margin: 8px;
@@ -119,8 +119,12 @@ header a
119 border-radius: 10px; 119 border-radius: 10px;
120 padding: 5px; 120 padding: 5px;
121} 121}
122.header_content
123{
124 padding: 20px 0;
125}
122 126
123@media screen and (max-width: 1000px){ 127@media screen and (max-width: 1024px){
124 .header_content 128 .header_content
125 { 129 {
126 padding: 15px 0; 130 padding: 15px 0;
@@ -130,20 +134,25 @@ header a
130 max-width: 160px; 134 max-width: 160px;
131 } 135 }
132} 136}
133@media screen and (max-width: 800px){ 137@media screen and (max-width: 768px){
134 .header_content 138 .header_content
135 { 139 {
136 grid-template-columns: 2fr 1fr; /* on vire la colonne de gauche et on permet au deux autres de "se pousser" si besoin */ 140 /*grid-template-columns: 2fr 1fr;*/ /* on vire la colonne de gauche et on permet au deux autres de "se pousser" si besoin */
137 padding: 10px; 141 /*padding: 10px;*/
142 display: block;
143 max-width: 65%;
144 margin: auto;
138 } 145 }
139 .header_left_col 146 .header_left_col
140 { 147 {
141 display: none; 148 display: none;
142 } 149 }
143} 150}
144@media screen and (max-width: 600px){ 151@media screen and (max-width: 480px){
145 .header_content 152 .header_content
146 { 153 {
147 display: block; 154 /*display: block;*/
155 max-width: 100%;
156 padding: 10px;
148 } 157 }
149} \ No newline at end of file 158} \ No newline at end of file
diff --git a/public/css/nav.css b/public/css/nav.css
index a9bddf2..4c276be 100644
--- a/public/css/nav.css
+++ b/public/css/nav.css
@@ -1,7 +1,7 @@
1/*-- menu principal --*/ 1/*-- menu principal --*/
2 2
3/* version horizontale */ 3/* version horizontale */
4@media screen and (min-width: 601px){ 4@media screen and (min-width: 769px){
5 .nav_button{ 5 .nav_button{
6 display: none; 6 display: none;
7 } 7 }
@@ -32,21 +32,28 @@
32 border-top: 3px solid #13aff0; 32 border-top: 3px solid #13aff0;
33 } 33 }
34 /* élément du menu survolé, le positionnement relatif en fait la référence du positionnement suivant */ 34 /* élément du menu survolé, le positionnement relatif en fait la référence du positionnement suivant */
35 .drop-right .sub-menu 35 .drop-right .sub-menu, .drop-left .sub-menu
36 { 36 {
37 position: absolute; /* positionnement par rapport au précédent "position" en CSS */ 37 position: absolute; /* positionnement par rapport au précédent "position" en CSS */
38 left: 100%;
39 top: -3px; /* la bordure bleue fait 3px */ 38 top: -3px; /* la bordure bleue fait 3px */
40 } 39 }
40 .drop-right .sub-menu{
41 left: 100%;
42 }
43 .drop-left .sub-menu{
44 right: 100%;
45 }
41 /* 1er sous-menu, poitionnement pour ne pas aggrandir l'élément parent */ 46 /* 1er sous-menu, poitionnement pour ne pas aggrandir l'élément parent */
42 nav > ul > li > ul 47 nav > ul > li > ul{
43 {
44 position: absolute; /* retire du flux, positionnement par rapport à la fenêtre */ 48 position: absolute; /* retire du flux, positionnement par rapport à la fenêtre */
45 margin-top: 5px; 49 margin-top: 5px;
46 margin-left: -5px; 50 margin-left: -5px;
47 } 51 }
52 nav > ul > li > ul:has(.drop-left){
53 right: 0;
54 }
48 55
49 @media screen and (max-width: 1000px){ /* entre 601 et 1000 */ 56 @media screen and (max-width: 1024px){ /* entre 769 et 1024 */
50 .nav_main p 57 .nav_main p
51 { 58 {
52 font-size: 90%; 59 font-size: 90%;
@@ -54,33 +61,31 @@
54 } 61 }
55 62
56 @media (pointer: fine){ 63 @media (pointer: fine){
57 .nav_main > ul > li:hover 64 .nav_main > ul > li:hover{
58 {
59 background-color: white; 65 background-color: white;
60 } 66 }
61 .drop-right > a > p:after{ 67 .drop-right > a > p:after{
62 content: " ▶"; 68 content: " ▶";
63 } 69 }
70 .drop-left > a > p:before{
71 content: "◀ ";
72 }
64 } 73 }
65} 74}
66@media screen and (max-width: 450px){ 75@media screen and (max-width: 480px){
67 .sub-menu p{ 76 .sub-menu p{
68 font-size: 90%; 77 font-size: 90%;
69 } 78 }
70} 79}
71 80
72@media screen and (min-width: 1000px){ 81@media screen and (min-width: 1025px){
73 nav > ul > li > ul{
74 margin-left: -7px; /* annuler le déplacement dû au padding: 7px; dans ".nav_main li" */
75 margin-top: 7px;
76 }
77 .nav_main li{ 82 .nav_main li{
78 padding: 7px; 83 padding: 7px;
79 } 84 }
80} 85}
81 86
82/* version petits écrans */ 87/* version petits écrans */
83@media screen and (max-width: 600px){ 88@media screen and (max-width: 768px){
84 #nav_zone{ 89 #nav_zone{
85 display: flex; 90 display: flex;
86 flex-direction: column; 91 flex-direction: column;
@@ -119,31 +124,40 @@
119 padding-left: 25px; 124 padding-left: 25px;
120 padding-right: 5px; 125 padding-right: 5px;
121 } 126 }
122
123 /*nav > ul > li > ul{ 127 /*nav > ul > li > ul{
124 margin-left: 0; 128 margin-left: 0;
125 }*/ 129 }*/
130
126 @media (pointer: fine){ 131 @media (pointer: fine){
127 .nav_main > ul > li:hover{ 132 .nav_main > ul > li:hover{
128 background-color: yellow; 133 background-color: yellow;
129 } 134 }
130 .drop-right > a > p:after{ 135 .drop-right > a > p:after, .drop-left > a > p:after{
131 content: ' ▼'; 136 content: ' ▼';
132 } 137 }
133 } 138 }
139
140 @media (pointer: coarse){
141 .drop-down.open, .drop-right.open, .drop-left.open{
142 border-radius: 5px;
143 }
144 }
134} 145}
135 146
136 147
137.nav_main 148.nav_main{
138{
139 border: 2px solid #13aff0; 149 border: 2px solid #13aff0;
140 text-wrap: nowrap; 150 text-wrap: nowrap;
141} 151}
142.sub-menu{ 152.sub-menu{
143 box-shadow: 1px 1px 3px black; 153 box-shadow: 1px 1px 3px black;
144} 154}
155.sub-menu:has(.drop-left), .sub-menu:has(.drop-left) .sub-menu{
156 box-shadow: -1px 1px 3px black;
157}
145ul{ 158ul{
146 margin: 0; 159 margin-top: 0;
160 margin-bottom: 0;
147} 161}
148 162
149.nav_main p 163.nav_main p
@@ -166,15 +180,15 @@ li:not(.current){
166 background-color: initial; 180 background-color: initial;
167 font-weight: initial; 181 font-weight: initial;
168} 182}
183.drop-down.open, .drop-down:hover{
184 position: relative; /* permet d'aligner son enfant en position absolue à droite avec un right: 0; */
185}
169 186
170 187
171/* sous-menus avec PC + souris 188/* sous-menus avec PC + souris
172mettre ici tous les blocs avec :hover, les navigateurs mobiles "simulent" les :hover, cassant le JS utilisé ici */ 189mettre ici tous les blocs avec :hover, les navigateurs mobiles "simulent" les :hover, cassant le JS utilisé ici */
173@media (pointer: fine) /* fine => précision de la souris */ 190@media (pointer: fine){ /* fine => précision de la souris */
174{ 191 .drop-down:hover > .sub-menu, .drop-right:hover > .sub-menu, .drop-left:hover > .sub-menu{
175 .drop-down:hover > .sub-menu,
176 .drop-right:hover > .sub-menu
177 {
178 display: block; 192 display: block;
179 } 193 }
180 .sub-menu li:hover /* écrase le fond blanc placé en même temps */ 194 .sub-menu li:hover /* écrase le fond blanc placé en même temps */
@@ -187,7 +201,7 @@ mettre ici tous les blocs avec :hover, les navigateurs mobiles "simulent" les :h
187 content: ' ▼'; 201 content: ' ▼';
188 font-size: x-small; 202 font-size: x-small;
189 } 203 }
190 .drop-right > a > p:after 204 .drop-right > a > p:after, .drop-left > a > p:before
191 { 205 {
192 font-size: x-small; 206 font-size: x-small;
193 } 207 }
@@ -203,22 +217,21 @@ mettre ici tous les blocs avec :hover, les navigateurs mobiles "simulent" les :h
203 font-size: x-small; 217 font-size: x-small;
204 vertical-align: text-bottom; 218 vertical-align: text-bottom;
205} 219}
220.sub-menu{
221 display: none;
222 background-color: white;
223 font-size: 95%;
224}
206 225
207/* écran tactile */ 226/* écran tactile */
208@media (pointer: coarse) /* coarse = grossier = précision écran tactile */ 227@media (pointer: coarse){ /* coarse = grossier = précision écran tactile */
209{
210 .sub-menu-toggle{ 228 .sub-menu-toggle{
211 display: inline-block; /* visible sur écran tactile */ 229 display: inline-block; /* visible sur écran tactile */
212 } 230 }
213 .drop-down.open > .sub-menu, .drop-right.open > .sub-menu{ 231 .drop-down.open > .sub-menu, .drop-right.open > .sub-menu, .drop-left.open > .sub-menu{
214 display: block; 232 display: block;
215 } 233 }
216 .drop-down.open, .drop-right.open{ 234 .drop-down.open, .drop-right.open, .drop-left.open{
217 background-color: yellow; 235 background-color: yellow;
218 } 236 }
219} 237} \ No newline at end of file
220.sub-menu{
221 display: none;
222 background-color: white;
223 font-size: 95%;
224}
diff --git a/public/js/main.js b/public/js/main.js
index 7020971..c8e10b0 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -59,6 +59,21 @@ function toggleTouchMenu(){
59 } 59 }
60} 60}
61 61
62function makeDropLeftMenuEntries(){
63 // détection d'éléments de 1er niveau possédant un menu déroulant possédant un menu déroulant
64 document.getElementById('nav_zone').querySelector('.nav_main').querySelectorAll('.drop-down:has(.drop-right)').forEach(drop_down => {
65 const rect = drop_down.getBoundingClientRect(); // coordonnées spatiales
66
67 // il se situe dans la moitié droite
68 if((rect.width / 2 + rect.left) > (window.innerWidth / 2)){ // centre de l'élément > largeur de la fenêtre?
69 drop_down.querySelectorAll('.drop-right').forEach(drop_right => {
70 drop_right.classList.remove('drop-right');
71 drop_right.classList.add('drop-left');
72 });
73 }
74 });
75}
76
62// exécuté à la fin du chargement de la page 77// exécuté à la fin du chargement de la page
63document.addEventListener('DOMContentLoaded', () => { 78document.addEventListener('DOMContentLoaded', () => {
64 79
@@ -70,17 +85,18 @@ document.addEventListener('DOMContentLoaded', () => {
70 85
71 // fermer les autres sous-menus de même niveau 86 // fermer les autres sous-menus de même niveau
72 // :scope pour pouvoir utiliser > pour restreindre aux frères directs 87 // :scope pour pouvoir utiliser > pour restreindre aux frères directs
73 li.parentElement.querySelectorAll(':scope > .drop-down, :scope > .drop-right').forEach(sibling => { 88 li.parentElement.querySelectorAll(':scope > .drop-down, :scope > .drop-right, :scope > .drop-left').forEach(sibling => {
74 if(sibling !== li){ 89 if(sibling !== li){
75 sibling.classList.remove('open'); // fermer sous-menus frères 90 sibling.classList.remove('open'); // fermer sous-menus frères
76 sibling.querySelectorAll('.drop-right').forEach(desc => { 91 sibling.querySelectorAll('.drop-right, .drop-left').forEach(desc => {
77 desc.classList.remove('open'); // fermer sous-menus neveux 92 desc.classList.remove('open'); // fermer sous-menus neveux
78 }); 93 });
79 } 94 }
80 }); 95 });
81 96
82 if(!li.classList.toggle('open')){ // ouvrir ou fermer ce sous-menu 97 // ouvrir ou fermer un sous-menu
83 li.querySelectorAll('.drop-right').forEach(desc => { 98 if(!li.classList.toggle('open')){
99 li.querySelectorAll('.drop-right, .drop-left').forEach(desc => {
84 desc.classList.remove('open'); // fermer sous-menus enfants 100 desc.classList.remove('open'); // fermer sous-menus enfants
85 }); 101 });
86 } 102 }
@@ -88,6 +104,7 @@ document.addEventListener('DOMContentLoaded', () => {
88 }); 104 });
89 105
90 navHeight(); // hauteur de <nav> en fonction de celle du menu en position fixe 106 navHeight(); // hauteur de <nav> en fonction de celle du menu en position fixe
107 makeDropLeftMenuEntries(); // changer en drop-left les drop-right des éléments du menu dans la moitié droite de la fenêtre
91 insertLocalDates(); 108 insertLocalDates();
92}); 109});
93 110
@@ -95,7 +112,7 @@ function navHeight(){
95 const nav = document.querySelector('nav'); // détection 112 const nav = document.querySelector('nav'); // détection
96 const nav_zone = document.getElementById('nav_zone'); 113 const nav_zone = document.getElementById('nav_zone');
97 const resize_observer = new ResizeObserver(entries => { // param de type tableau 114 const resize_observer = new ResizeObserver(entries => { // param de type tableau
98 let nav_button_height = window.innerWidth <= 600 ? 26 : 0; // 26 = taille du bouton 115 let nav_button_height = window.innerWidth <= 768 ? 26 : 0; // 26 = taille du bouton
99 nav_button_height += nav.classList.contains('show') ? 15 : 0; 116 nav_button_height += nav.classList.contains('show') ? 15 : 0;
100 for(const entry of entries){ 117 for(const entry of entries){
101 nav_zone.style.height = (entry.contentRect.height + nav_button_height) + 'px'; 118 nav_zone.style.height = (entry.contentRect.height + nav_button_height) + 'px';