Witam!
Poprawiłem trochę kod i bardziej go opisałem aby lepiej było mi wyjaśnić z czym mam problem co sprawia mi zagmatwanie i czego nie rozumiem. Jeżeli ktoś miałby chwilę wolnego czasu to proszę o ocenę kodu i proszę o pomoc w pytaniach które zadaję tutaj:
1. Prosty pasek nawigacyjny
Kod na jsfiddle.net: https://jsfiddle.net/adriansikora344/h3cqu457/
2. Pasek nawigacyjny z listą rozwijaną
Kod na jsfiddle.net: https://jsfiddle.net/adriansikora344/ycLhf5dj/
3. Pasek nawigacyjny z podwójną listą rozwijaną
Kod na jsfiddle.net: https://jsfiddle.net/adriansikora344/du1wwtby/
1. Prosty pasek nawigacyjny
Cel:
Zwykłe menu przypięte z prawej strony pojemnika w którym się znajduje z podświetleniem przycisku nad którym znajduje się kursor.
Kod na jsfidlle.net: https://jsfiddle.net/adriansikora344/h3cqu457/
Kod HTML:
<header>
<nav class="main-navigation-bar">
<ul class="main-menu">
<li><a>Element 1</a></li>
<li><a>Element 2</a></li>
<li><a>Element 3</a></li>
<li><a>Element 4</a></li>
</ul>
</nav>
</header>
Wyjaśnienie:
- W kodzie HTML nie ma żadnych odnośników do innych podstron ponieważ kliknięcie w element menu powoduje wywołanie funkcji JavaScript otwierające np. okienko typu modal;
- Znacznik header nie powinien wprowadzać żadnego stylu wpływającego na cechę/wygląd elementu. Nadany styl temu znacznikowi powinien jedynie dokować element w odpowiednim miejscu lub określać rozmiar nagłówka ( w tym przypadku menu ).
- Klasa .main-navigation-bar ustawia szerokość menu na szerokość pojemnika w którym się znajduje oraz ustawia kolor tła który będą dziedziczyć poszczególne elementy listy. Kolor tła jest ustawiany w tej klasie ponieważ w przypadku ustawienia cechy padding dla tej klasy tło będzie wystawać nad/pod elementy menu:
.main-navigation-bar { width: 100%; background: #777; }
Pytanie:
1.0 Czy tutaj width: 100%; jest potrzebne ? Jeżeli dokuję elementy do prawej strony to czy nie jest tak że szerokość paska nawigacyjnego automatycznie przyjmuje maksymalną wartość elementu rodzica ?
- Klasa .main-menu odpowiada za ustawienie trybu wyświetlania listy, położenia:
.main-menu {
display: flex;
justify-content: flex-end;
list-style-type: none;
}
- Ostylowanie poszczególnych elementów listy:
.main-menu > li { color: white; cursor: pointer; }
.main-menu > li:hover { color: black; background: #ddd; }
.main-menu > li:active { color: white; background: black; }
.main-menu > li > a {
/* czemu tutaj nie mogę dodać padding jeżeli nie ustawię flagi display:flex/block ? */
display: flex;
padding: 20px;
text-align: center;
text-decoration: none;
}
Element <a> w liście nie ma wpisanej informacji odnośnie koloru czcionki oraz koloru tła. Dziedziczy on te cechy z elementu rodzica czyli <li> co skutkuje również zmianą tych cech poprzez pseudoklasę :hover oraz :active elementu <li> w którym znajduje się omawiany znacznik <a>. Pseudoklasa :hover i :active do zmiany wyglądu nie jest bezpośrednio nadana elementowi <a> ponieważ zmieniając wtedy tło elementu zmieniło by się tylko tło tekstu a nie cały przycisk.
Pytania:
1.1 Tutaj zastanawia mnie dlaczego ustawiając np. padding: 30px; w klasie .main-menu>li> a to zmienia się jedynie szerokość elementu a nie jego wysokość ? Problem przestaje istnieć jeżeli w tej klasie dodam cechę display: flex/block; wtedy bez problemu mogę ustawić padding dla elementu <a>. Dlaczego tak się dzieje ?
1.2 Tutaj jest rozbicie menu na dwie klasy, tylko co jeżeli chciałbym mieć na stronie drugie menu ? Nie mogę już użyć klasy .main-menu. Rozwiązaniem na to jest albo nadanie innej nazwy klasy albo dodanie .main-navigation-bar > .main-menu co powoduje „zaciemnienie” kodu.Jedyne rozwiązanie to preprocesory ? Czy to normalne że jest pełno selektorów w stylu ?
2. Pasek nawigacyjny z listą rozwijaną
Cel:
Dodanie do poprzedniego paska nawigacyjnego listy rozwijanej. Zadokowanie listy rozwijanej tak aby prawy koniec menu przylegał do prawej krawędzi menu rozwijanego ( wystawał i zwiększał swoją szerokość z lewej strony a nie jak jest standardowo z prawej ).
Kod na jsfiddle.net: https://jsfiddle.net/adriansikora344/ycLhf5dj/
Kod HTML:
<header>
<nav class="main-navigation-bar">
<ul class="main-menu">
<li><a>Element 1</a></li>
<li><a>Element 2</a></li>
<li class="menu-item-has-children">
<a>Element 3</a>
<ul class="sub-menu">
<li><a>sub 1</a></li>
<li><a>sub 2 bardzo długi element</a></li>
<li><a>sub 3</a></li>
<li><a>sub 4</a></li>
<li><a>sub 5</a></li>
</ul>
</li>
<li><a>Element 4</a></li>
</ul>
</nav>
</header>
Wyjaśnienie:
Rozwijane menu to nic innego jak zagnieżdżona lista z domyślną flagą display: none; która zmienia się na display: block; przy aktywacji pseudoklasy :hover elementu rodzica tej listy.
- Klasy .main-navigation-bar oraz .main-menu są identyczne jak w poprzednim przykładzie. Różni się tylko klasa .main-menu > li ponieważ została do niej dodana flaga display: block; ponieważ domyślnie ukryta lista z rozwijanym menu ma być wyświetlona bezpośrednio pod elementem <a>.
Pytania:
2.0 Czy te display: block jest tutaj potrzebne ? Podobno jest już tutaj domyślnie ustawione. Jeżeli chciałbym mieć rozwijane menu kolejnego stopnia to bardziej pasuje tutaj flaga display: flex; ponieważ bez problemu mogę wybierać kierunek menu, czy column czy block. Zgadza się ?
- NOWA KLASA: .menu-item-has-children dodaje ona strzałkę informującą użytkownika o tym że ten element zawiera rozwijane menu.
.menu-item-has-children > a:after { content: '\25BC'; padding-left: 10px; }
Selektor > został użyty aby strzałka została dodana do pierwszego napotkanego elementu <a>.Ta klasa służy też do wyświetlenia rozwijanego menu które domyślnie ma ustawioną flagę display: none;
.main-menu > .menu-item-has-children:hover > .sub-menu {
display: block;
padding-left: 0; /* Dlaczego jeżeli nie mam tutaj tego ustawionego to text nie przylega do lewej krawędzi ? */
}
Pytania:
2.1 Skoro używam flex’y to tutaj nie powinienem mieć display: flex; z atrybutem column ? Patrząc na inne przykłądy to wszędzie jest display: block; Ponieważ lista musi być wyświetlona pod elementem <a>. ( Pytam o to co wcześniej )
2.2 Dlaczego jeżeli nie mam tutaj ustawionej flagi padding-left 0; to text nie przylega do lewej krawędzi ? Tylko jest wyświetlany od środka ?
- Klasa .sub-menu
.sub-menu {
display: none;
position: absolute;
z-index: 1;
list-style-type: none;
background: white; /* Kolor tła nie jest dziedziczony ! */
}
Pytanie: 2.3 Dlaczego kolor tła nie jest dziedziczony ? Przecież jest ustawiony w klasie .main-navigation-bar.
.sub-menu > li { display: flex;}
.sub-menu > li:hover { background: black; color: white; }
.sub-menu > li > a {
padding: 20px;
text-align: center;
text-decoration: none;
}
Pytania:
2.4 Rozwijana lista ma szerokość najdłuższego elementu i rozciąga się w prawą stronę. Przylega lewą krawędzią do lewej krawędzi elementu <a> który rozwija tą listę tylko jak zrobić aby lista przylegała do tego elementu prawą krawędzią i rozciągała się w lewą stronę ?
2.5 Tutaj nie jest dodany żaden tag position: relative; dla elementu rozwijającego listę. Czy on musi być ? Dodanie tej flagi skutkuje że szerokość rozwijanej listy jest taka sama jak szerokość przycisku rozwijanego. Mogę zmienić tą szerokość zmieniając width elementu. Ale wolę aby została automatycznie ustawiona na szerokość najdłuższego elementu.
3. Pasek nawigacyjny z podwójną listą rozwijaną
Cel:
Rozwijane menu trzeciego stopnia tak aby było wyświetlane z lewej strony
Kod na jsfiddle.net: https://jsfiddle.net/adriansikora344/du1wwtby/
Kod HTML:
<header>
<nav class="main-navigation-bar">
<ul class="main-menu">
<li><a>Element 1</a></li>
<li><a>Element 2</a></li>
<li class="menu-item-has-children">
<a>Element 3</a>
<ul class="sub-menu">
<li><a>sub 1</a></li>
<li class="menu-item-has-children">
<a>sub 2 - bardzo długi element</a>
<ul class="second-st-sub-menu">
<li><a>sub 1</a></li>
<li><a>sub 2</a></li>
<li><a>sub 3</a></li>
<li><a>sub 4</a></li>
<li><a>sub 5</a></li>
</ul>
</li>
<li><a>sub 3</a></li>
<li><a>sub 4</a></li>
<li><a>sub 5</a></li>
</ul>
</li>
<li><a>Element 4</a></li>
</ul>
</nav>
</header>
Wyjaśnienie:
- NOWE KLASY . second-st-sub-menu jest to klasa reprezentująca wyświetlenie menu trzeciego stopnia. Zasada działania jest identyczna jak poprzednio.
Klasa ta jest osadzona w elemencie <li> który ma ustawioną flagę display: flex; więc menu trzeciego stopnia będzie przylegało do elementu <li> który zawiera tą klasę. Teoretycznie aby wyświetlić te menu z lewej strony należy nadać flex-direction: row-reverse ale nie wiem czemu to nie działa.
- Wyświetlenie menu trzeciego stopnia
.sub-menu > .menu-item-has-children:hover > .second-st-sub-menu { display: block; }
Pytanie:
3.0 Tak jak poprzednio, skoro używam już flex’y to nie powinienem użyć tutaj flagi display: flex; a atrybutem column ? ( pytam o to co poprzednio )
- Klasa reprezentująca menu trzeciego stopnia:
.second-st-sub-menu {
display: none;
position: absolute;
z-index: 1;
margin: 0 0 0 100%; /* Wyświetlenie menu z prawej strony */
padding-left: 0; /* Bez wyzerowania padding-left menu odstaje, dziedziczy od lementu <a> ? */
}
Pytania:
3.1 Tak jak w kodzie css, jak wyświetlić menu z lewej strony ?
3.2 Bez flagi padding-left: 0; menu odstaje od reszty, dziedziczy od elementu <a> ?