Css - yet another tree view open / close and parent question - css

I'm fighting with this for 2 days and it may be simple, but I'm not getting there.
I want to have a nice, clean tree view with multiple levels and I'm trying to first target children after root. I can do that, but I'm sure using ~ and + signs this may be simpler. Second I need the checkboxes to open / close the tree.
I know I can always use a pre made one, but I want need to learn.
Any help?
No javascript or query, pure css please.
ul.tree li a {
/* 1º Nível */
color: red;
}
ul.tree ul>li a {
/* 2º Nível */
color: blue;
}
ul.tree ul>ul li a {
/* 3º Nível */
color: yellow;
}
ul.tree ul>ul>ul li a {
/* 4º Nível */
color: green;
}
ul.tree ul>ul>ul>ul li a {
/* 5º Nível */
color: orange;
}
ul.tree>input.[type=checkbox]:checked ul.tree ul>li {
display: none;
}
<ul class="tree">
<li><input type=checkbox /><b>_root</b></li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li>
<ul class="pasta">
<li><input type=checkbox /><b>Pasta A</b></li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li>
<ul class="pasta">
<li><input type=checkbox /><b>Pasta A - 1</b></li>
<li class="ficheiro">ficheiro</li>
<li>
<ul class="pasta">
<li><input type=checkbox /><b>Pasta dentro da pasta A - 1</b></li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li>
<ul class="pasta">
<li><input type=checkbox /><b>Pasta dentro da pasta dentro da pasta A -1</b></li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
</ul>
</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
</ul>
</li>
<li class="ficheiro">ficheiro</li>
</ul>
</li>
<li class="ficheiro">ficheiro</li>
</ul>
</li>
<li class="ficheiro">ficheiro</li>
<li class="ficheiro">ficheiro</li>
</ul>
the fiddle
example of what I made

Here's the code, and later I will link to the documentation and explain what I have done. I have validated the HTML. Strange syntax in CSS that you're seeing is BEM methodology. You should avoid targeting bare elements and always try to give them specific class.
JSFiddle - if you find it easier.
Please note: Although I have tried to use best practices both for HTML and CSS, this is NOT something you would do in production. It is too "hacky" and the "price" for pure css solution is much higher than if we decided to use a little bit of JS. But, nevertheless it was interesting to try and overcame the obstacles, that is - to propose the solution within the boundaries you have set.
label {
font-weight: bold;
}
/* LIST style hacks which allows us to avoid bullets before checkbox - unfortunately, we have to supply and fake the bullets with pseudo before element for every li where we want them */
ul {
list-style: none;
}
.ficheiro::before {
content: "•";
position: absolute;
left: -15px;
}
.pasta-1 .ficheiro::before {
content: "°";
position: absolute;
left: -15px;
top: 3px;
}
.pasta-2 .ficheiro::before {
content: "*";
position: absolute;
left: -15px;
top: 3px;
}
/* CHECKBOX hacks for selectively hiding and showing the parts of the tree */
.tree {
display: none;
}
#level-0:checked ~ .tree {
display: block;
}
.pasta-1,
.pasta-2,
.pasta-3,
.pasta-4 {
display: none;
}
#level-1:checked ~ .pasta-1 {
display: block;
}
#level-2:checked ~ .pasta-2 {
display: block;
}
#level-3:checked ~ .pasta-3 {
display: block;
}
#level-4:checked ~ .pasta-4 {
display: block;
}
/* LINKS */
.ficheiro {
position: relative;
}
.ficheiro__link--root {
color: red;
}
.ficheiro__link--level-1 {
color: blue;
}
.ficheiro__link--level-2 {
color: yellow;
}
.ficheiro__link--level-3 {
color: green;
}
.ficheiro__link--level-4 {
color: orange;
}
<input id="level-0" type="checkbox" />
<label for="level-0">_root</label>
<ul class="tree">
<li class="ficheiro"><a class="ficheiro__link--root" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--root" href="#">ficheiro</a></li>
<li>
<input id="level-1" type="checkbox" />
<label for="level-1">Pasta A</label>
<ul class="pasta-1">
<li class="ficheiro"><a class="ficheiro__link--level-1" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-1" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-1" href="#">ficheiro</a></li>
<li>
<input id="level-2" type="checkbox" />
<label for="level-2">Pasta A - 1</label>
<ul class="pasta-2">
<li class="ficheiro"><a class="ficheiro__link--level-2" href="#">ficheiro</a></li>
<li>
<input id="level-3" type="checkbox" />
<label for="level-3">Pasta dentro da pasta A - 1</label>
<ul class="pasta-3">
<li class="ficheiro"><a class="ficheiro__link--level-3" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-3" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-3" href="#">ficheiro</a></li>
<li>
<input id="level-4" type="checkbox" />
<label for="level-4">Pasta dentro da pasta dentro da pasta A -1</label>
<ul class="pasta-4">
<li class="ficheiro"><a class="ficheiro__link--level-4" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-4" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-4" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-4" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-4" href="#">ficheiro</a></li>
</ul>
</li>
<li class="ficheiro"><a class="ficheiro__link--level-3" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--level-3" href="#">ficheiro</a></li>
</ul>
</li>
<li class="ficheiro"><a class="ficheiro__link--level-2" href="#">ficheiro</a></li>
</ul>
</li>
<li class="ficheiro"><a class="ficheiro__link--level-1" href="#">ficheiro</a></li>
</ul>
</li>
<li class="ficheiro"><a class="ficheiro__link--root" href="#">ficheiro</a></li>
<li class="ficheiro"><a class="ficheiro__link--root" href="#">ficheiro</a></li>
</ul>
Try to understand what is happening in the code, and why I have structured it the way I have. It's best way to learn. Meanwhile, I will prepare the links and explanations and append them in the later edit.
EDIT:
You can validate code with w3c validator. It will scream at you
because we're missing <!DOCTYPE html>, lang, title, etc. but
the code itself is valid.
MDN - li element:
permitted parents: <ul>, <ol>, or <menu>
permitted content: Flow content (basically, any element that is valid within <body>)
30 CSS selectors you should know - we were using sibling combinator ~ (number 9 on this list of 30)
CSS code could be much cleaner with the use of preprocessor such as SASS and mixins, or even with the simple nesting.
When you target elements several levels deep, you're increasing the specificity and make it extremely hard to maintain it later. You can try this specificity calculator to understand it better. That's why one of the best practices is to use classes. With good naming, the code basically documents itself and it's quite clear what your intention was. You immediately know which element belongs to which level just by looking at the class names.

Related

using + with > selector

I am learning responsive menus and by googling, i got the hamburger checkbox hack.
What i am trying to do is show only direct descendants by clicking the hamburger and hide the sub menus.
#toggle-menu {
cursor: pointer;
}
#primary-nav,
#menu-toggle,
#primary-nav>ul {
display: none;
}
#menu-toggle:checked+#primary-nav {
display: block;
}
<link href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" rel="stylesheet" />
<div class="menu">
<a href="#">
<h1>Company</h1>
</a>
<label for="menu-toggle" id="toggle-menu"><i class="far fa-bars"></i></label>
<input type="checkbox" id="menu-toggle">
<ul id="primary-nav">
<li>home</li>
<li>dropdown
<ul>
<li>sub1</li>
<li>sub2</li>
</ul>
</li>
</ul>
</div>
Any help will be appreciated
To only show the ul after the input, you need to hide all uls, then only show the ul directly after a checked input
You can then add a class on all the inputs and do the same for the submenu.
#toggle-menu {
cursor: pointer;
}
.toggler, /*checkboxes a class of toggler and hide */
ul { /* hide all menus (you may want to give them all a class) */
display: none;
}
.toggler:checked+ul { /* only show a ul if it is directly after a checked toggler input */
display: block;
}
<link href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" rel="stylesheet" />
<div class="menu">
<a href="#">
<h1>Company</h1>
</a>
<label for="menu-toggle" id="toggle-menu"><i class="far fa-bars"></i></label>
<input type="checkbox" id="menu-toggle" class="toggler">
<ul id="primary-nav">
<li>home</li>
<li>
<label for="sub-menu1">dropdown</label> <!-- use a label and target the checkbox below -->
<input type="checkbox" class="toggler" id="sub-menu1"> <!-- add this -->
<ul>
<li>sub1</li>
<li>sub2</li>
</ul>
</li>
</ul>
</div>

CSS: How to select a specific sibiling element

I need to know how I can select the <li>Iquitos Peru</li> tag using CSS, I have read about "nth-child" but I do not understand it. I have the following sample code.
<ul id="pais">
<h1>Perú</h1>
<li class="departamento">
<ul>
<h2>Lima</h2>
<li class="provincia">
<h3>Lima</h3>
<ul>
<li><strong>Ciudades:</strong></li>
<li>Ancon</li>
<li>Comas</li>
<li>Los Olivos</li>
<li>La Molina</li>
<li>Chorrillos</li>
<li><input type="text" class="eleccion"></li>
</ul>
</li>
</ul>
</li>
<li class="departamento">
<ul>
<h2>Loreto</h2>
<li class="provincia">
<h3>Iquitos Ciudad</h3>
<ul>
<li><strong>Ciudades:</strong></li>
<li>Iquitos Perú</li> <-- I need format this ######
<li>Nauta</li>
<li>Belén</li>
<li>Punchana</li>
<li><input type="text" class="eleccion"></li>
</ul>
</li>
</ul>
</li>
</ul>
<input type="button" value="Enviar" class="btnEnviar" (click)="alert()">
I found this example but I do not know how I can apply it to my case. Is that in this example only divs are used, and I have <ul> I find this but is difficult to understand. Thank you very much.
One way is selecting it like this if you know that the order is not going to change
#pais .departamento:last-child .provincia li:nth-child(2) {
color: red;
}
or using both times the nth-child selector
#pais .departamento:nth-child(3) .provincia li:nth-child(2) {
color: red;
}
Not possible to select the content with CSS. So added a value attribute to the li for selector.
Alternatively if you are using jquery then you can use the contains selector
li[value='Iquitos Per'] {
background-color:red
}
<ul id="pais">
<h1>Perú</h1>
<li class="departamento">
<ul>
<h2>Lima</h2>
<li class="provincia">
<h3>Lima</h3>
<ul>
<li><strong>Ciudades:</strong></li>
<li>Ancon</li>
<li>Comas</li>
<li>Los Olivos</li>
<li>La Molina</li>
<li>Chorrillos</li>
<li><input type="text" class="eleccion"></li>
</ul>
</li>
</ul>
</li>
<li class="departamento">
<ul>
<h2>Loreto</h2>
<li class="provincia">
<h3>Iquitos Ciudad</h3>
<ul>
<li><strong>Ciudades:</strong></li>
<li value="Iquitos Per">Iquitos Perú</li>
<li>Nauta</li>
<li>Belén</li>
<li>Punchana</li>
<li><input type="text" class="eleccion"></li>
</ul>
</li>
</ul>
</li>
</ul>
<input type="button" value="Enviar" class="btnEnviar" (click)="alert()">
You can either give that <li> an id or a class. Otherwise you can use a selector, see: Nested classes selectors

How can i disable navigation active

navigation image here
how can i disable the green color there whenever i click in gallery page?
Home
<li class="dropdown mega-dropdown">
<a class="dropdown-toggle" href="Gallery.aspx">Gallery<span class="caret"></span></a>
<div class="pc-nav">
<ul class="dropdown-menu mega-dropdown-menu">
<li class="col-sm-3 col-md-push-3">
<ul>
<li class="dropdown-header" style="text-align:left">Company Trips</li>
<li style="text-align:left; visibility:hidden;"> 2016 - Vietnam</li>
<li style="text-align:left;"> 2015 - Guilin</li>
</ul>
</li>
</ul>
CSS here
<ul class="dropdown-menu mega-dropdown-menu">
<li class="col-sm-3 col-md-push-3">
<ul>
<li class="dropdown-header" style="text-align:left">Company Trips</li>
<li style="text-align:left;"> 2016 - Vietnam</li>
<li style="text-align:left;"> 2015 - Guilin</li>
</ul>
</li>
</ul>
I assume the current class indicates the column you have selected. Given the markup you provided in the comments, you can rewrite the rule like this to remove the background color:
.current {
background-color: transparent;
}
If you do not have access to the original code but wish to override it, you can supersede the background-color property like this:
.current {
background-color: transparent !important;
}
But in the end, if you don't wish there to be any special background color for the current column, you can just delete the entire block of code.
EDIT
Based on your feedback, I assume you want to highlight the names of the countries in the list but not the first item of the list. In that case, you can target them like this:
ul.dropdown-menu ul li:not(.dropdown-header) {
background-color: #00b200;
}

Two simple CSS problems

I have two simple problems I couldn't fix:
When over "Home" you can see the borders are no longer in radius.
What can I do to fix it?
When over "Services" There's this gray line
on the top-right of the popup menu. I want to discard it.
<nav>
<ul>
<li><a id="homefix" href="#">HOME</a></li>
<li>ABOUT</li>
<li><a id="serv" href="#">SERVICES</a>
<ul>
<li>Web Design</li>
<li>Programming</li>
<li><a id="ecomfix" href="#">e-Commerce</a></li>
</ul>
</li>
<li>CONTACTS</li>
<form>
<input type="submit" class="searchsubmit" value="Search" />
<input type="text" class="search" placeholder="Search" />
</form>
</ul>
</nav>
http://jsfiddle.net/yuvalsab/M9D89/
Thank you very much! :)
nav ul li:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
nav ul li:last-child {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
http://jsfiddle.net/M9D89/6/
Applying a full border radius seems to work. It doesn't look bad, and the border radius doesn't seem to be applied in #homefix. Why can't you just do this:
http://jsfiddle.net/M9D89/3/

Add an autoincremental value with css counter

I want to add an incremental value through CSS, but apparently i am doing something wrong.
HTML
<ul role="menu" style="left: 0px; position: absolute; top: 0px;">
<li id="Slideshow-13675338798500">
<a class="slideshow-thumbnails-hidden" href="images/slideshow/slide-1.png" role="menuitem" tabindex="0">
<span class="thmubbutton"></span>
</a>
</li>
<li id="Slideshow-13675338798501">
<a class="slideshow-thumbnails-hidden" href="images/slideshow/slide-2.png" role="menuitem" tabindex="1">
<span class="thmubbutton"></span>
</a>
</li>
<li id="Slideshow-13675338798502">
<a class="slideshow-thumbnails-hidden" href="images/slideshow/slide-3.png" role="menuitem" tabindex="2">
<span class="thmubbutton"></span>
</a>
</li>
</ul>
css
span.thmubbutton{
counter-increment: myIndex;
}
span.thmubbutton:before
{
content:counter(myIndex);
}
The output is 1 | 1 | 1
DEMO
You need to reset your counter to 0 before using it.
body {
counter-reset: myIndex;
}
Fiddle: http://jsfiddle.net/ZgEgS/1/
More info on counters here: https://developer.mozilla.org/en-US/docs/CSS/Counters
I don't believe that CSS supports this natively. There's something called LESS (http://lesscss.org/) that does support increments. Try giving it a spin.
EDIT: nevermind... I believe I was wrong. Still, LESS is a good alternative as well. So I won't delete my answer ;)

Resources