hamburger dropdown css display property - css

I have a CSS media query / flexbox style that assigns a "display: none" to a navigation div after it goes to the max-width of 768px. Using Javascript, I was able to toggle display: "block" and "none" using an if/else statement once my hamburger button is pressed.
However, the pain point is that once I toggle it to "display: none", the navbar is now gone once the screen is beyond the designated width; and hamburger menu only appears at the smaller width size.
It seems like the toggle permanently assigns "display: none" to it. How would I remove the "display: none" back to "display: block" without clicking on hamburger button?
const burgerBar = document.querySelector('.burger');
const navigation = document.querySelector('.navigation');
const navbarItems = document.querySelector('.navbar-items');
const navbarItem = document.querySelector('.navbar-item');
burgerBar.addEventListener('click', () => {
if (navigation.style.display != 'block') {
navigation.style.display = 'block'
} else {
navigation.style.display = 'none'
}
})
#media screen and (max-width: 768px) {
/* width below 768 */
.header-container {
padding: 15px;
}
.navigation {
display: none;
}
.burger {
display: block;
}
}
<div class="navigation">
<nav class="navbar-container">
<ul class="navbar-items">
<li class="navbar-item">Home</li>
<li class="navbar-item">Projects</li>
<li class="navbar-item">Github</li>
<li class="navbar-item">About</li>
<li class="navbar-item">Contact</li>
</ul>
</nav>
</div>
<div class="burger">
<div class="bar-one"></div>
<div class="bar-two"></div>
<div class="bar-three"></div>
</div>

what you are doing with javascript is using inline-styles for the tag itself
for eaxmple
navigation.style.display = 'block'
will make it like this
<div style="display:none;"> </div>
but what you are doing with css using classes can't override the inline-styles
due to CSS Specificity
Every selector has its place in the specificity hierarchy. There are
four categories which define the specificity level of a selector:
Inline styles - An inline style is attached directly to the element to
be styled. Example: .
IDs - An ID is a unique identifier for the page elements, such as
#navbar.
Classes, attributes and pseudo-classes - This category includes
.classes, [attributes] and pseudo-classes such as :hover, :focus etc.
Elements and pseudo-elements - This category includes element names
and pseudo-elements, such as h1, div, :before and :after.
solution:
use javascript to toggle a class (instead of changing the property directly) that hides the navigation

solved! The display_toggle class need to be after the media query...I believe that has something to do with specificity that.

Related

CSS media query print:

Doing a page, html result like:
<div class="container table-page">
<div class="selected-block"> some info here </div>
<h1>Table header</h1>
<div class="notice-calc print-shown">Notices !</div>
<table class="input-data">...</table>
<button class="js-btn-add-row">Add row to a input table</button>
<button class="js-calculate">Calculate table values</button>
<div class="js-waiting" style="display: none;">Progress bar</div>
<table class="calc-result" style="display:none;">...</table>
</div>
Main idea of styles below - hide every direct children of '.container' except tables and some table elements with class="print-hidden" will be hidden too. For print version of page using rule:
#media print {
.container> :not(table),
.print-hidden {
display: none;
}
.print-shown {
display: block;
}
}
Later added notices must be shown at print version too, but it does not appear. Nevertheless if edit '.print-shown' rule like:
.container .print-shown {
display: block;
}
Then it shows. Tested in Chrome 88.0.4324.190 (Official Build) (64-bit)/ Dev.Firefox 86.0b9 (64x)/ Opera 74.0.3911.107. And Edge shows it in both cases.
Why single class selector does not work here?
It is because of this selector:
.container > :not(table)
It targets all direct children of .container (which is not a table). This also includes children with the .print-shown-class.
So, when you have a .print-shown element as a child of .container, the .container > :not(table) has presedence over the .print-shown class (because the first selector is more specific than the latter)

Select "toolbar-title" within shadow root of ion-title via css

In Ionic, the ion-title component has the content encapsulated in an extra div within its shadow-dom.
This div has the class .toolbar-title set. How can i select this div via scss-selector to change its overflow behavior?
I tried:
.toolbar-title { ... }
ion-title .toolbar-title
ion-title::shadow .toolbar-title { ... }
ion-title::shadow(div) { ... }
and a lot other combinations including :host & ::ng-deep selectors.
And, yes i know , ::shadow and ng-deep is deprectaded.
I also know that ionic has introduced css-variables for this purposes, but unfortunatley not for the overflow attribute.
THX in advance!
The concept of shadowDOM is you can't touch its content with CSS from the outside.
It is an open shadowDOM, so you can change it with JavaScript.
document.querySelector("ion-title")
.shadowRoot
.querySelector(".toolbar-title")
.style
.overflow = "initial";
Ionic v6 allows you to target and modify shadowDOM contents with CSS. See https://ionicframework.com/docs/theming/css-shadow-parts
However, the element you want to select inside the shadowDOM needs to expose a part attribute. For instance the ion-select element:
<ion-select>
#shadow-root
<div part="placeholder" class="select-text select-placeholder"></div>
<div part="icon" class="select-icon"></div>
</ion-select>
You can select the placeholder element with:
ion-select::part(placeholder) {
color: blue;
opacity: 1;
}
Unfortunately, the ion-title element does not expose any shadow parts. You need to wrap the contents of ion-title in a container to be able to modify them:
<ion-title>
<div class="content">
<img src="..." />
Hello World!
</div>
</ion-title>
CSS:
.content {
display: flex;
align-items: center;
}
StackBlitz example: https://stackblitz.com/edit/ionic-title-modification-8a1qst

How can I place slotted elements into css grid?

My HTML is like this:
<div id="grid-container">
<slot name="items-to-be-filled"></slot>
</div>
I have formatted the above with CSS like this:
#grid-container {
display: grid;
}
However, the items that I filled into the slot seem to be out of order. I examined using developer's tool and found out that the slotted items are not being treated as grid items.
Is it possible to treat slotted items just as normal children nodes? Thanks.
The Shadow DOM isolate external from internet CSS styles.
As a consequence, and to be effective, the CSS property display: grid should be placed in the Shadow DOM.
host.attachShadow( { mode: 'open' } )
.innerHTML =
`<style>
#grid-container { display: grid }
</style>
<div id="grid-container">
<slot></slot>
</div>`
<div id="host">
<span>one</span>
<span>two</span>
<span>three</span>
</div>

Menu with hover, how to do it work in mobile?

I'm using Bootstrap 3. I have this menu which works ok only when is not a touch (mobile) device:
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Inicio</li>
<li>Ayuda</li>
<li>Metodología<span></span>
<div class="nav-sub-menu">
<ul class="text-submenu">
<li style="padding-left=0px">Guía Metodológica</li>
<li style="padding-left=0px">Modelos y Resultados</li>
</ul>
</div>
</li>
<li>Glosario</li>
<!--<li>Link de Interés</li>-->
<li>Contacto</li>
</ul>
</div>
In the css, the hover that give the style to the elements have this code:
.nav li > a {
display: table-cell;
}
.nav>li>a:hover {
background: none;
color: #ff7113;
}
.nav > li > ul {
display:none;
list-style:none;
position:relative;
}
.nav > li:hover > ul {
display:block;
}
I've read some posts about making menus for both desktop and touch without hover, with javascript or even using external libraries. Is there are more simple way to use this menu in mobiles devices?
I made a Jsfiddle with the menú working:
https://jsfiddle.net/esqkx349/
You have to open it in a wide screen to see it, like this:
in case, anyone still finding solution to this problem,
Add onclick="void(0)" in <div class="navbar-collapse collapse"> to make mobile device recognise an element as an element with a hover.
like <div class="navbar-collapse collapse" onclick="void(0)">
Well, I made it:
https://jsfiddle.net/pmiranda/bwkyocpa/1/
I had to put some javascript and css:
function isTouchDevice(){
return typeof window.ontouchstart !== 'undefined';
}
$(document).ready(function(){
/* If mobile browser, prevent click on parent nav item from redirecting to URL */
if(isTouchDevice()) {
// 1st click, add "clicked" class, preventing the location change. 2nd click will go through.
$(".navbar-nav > li > a").click(function(event) {
// Perform a reset - Remove the "clicked" class on all other menu items
$(".navbar-nav > li > a").not(this).removeClass("clicked");
$(this).toggleClass("clicked");
if ($(this).hasClass("clicked")) {
event.preventDefault();
}
});
}
});
CSS:
.hover-hack {
position: fixed !important;
background-color: rgba(0, 0, 0, 0.7) !important;
}
#media only screen and (max-width:1024px) {
.hover-hack {
background: rgba(0, 0, 0, 1) !important;
z-index: 10;
}
}
And the html:
<li>Metodología<span></span>
<ul class="text-submenu hover-hack">
<li style="padding-left=0px">Guía Metodológica</li>
<li style="padding-left=0px">Modelos y Resultados</li>
</ul>
</li>
<li>Glosario</li>
It's possible to make a clickable dropdown without Js.
The hover method is sketchy because some touch devices will treat the first click like a hover action.
It can be done using a checkbox html element. Then, css can detect wether or not the checkbox is current checked.
I created a component that does the job using this link. It works fairly well on mobile because click events work just fine.
Pure CSS clickable dropdown?
Problem is, this solution is slightly hacky and pure HTML, CSS implementations can't work outside of the HTML heirarchy.(so if your button and your dropdown menu exist in different branches of the html heirarchy it won't work.)
I think the most appropriate solution is to use a little bit of JS and handle the element on click.

CSS immediate child selector

#main .container > div:not(.sites):not(.default) {
display: none;
}
The <h1> tag is visible while the below yui-ge div tag is hidden. If > only applies to immediate children how come my yui-ge is having the above CSS applied to it (both in Chrome and Firefox).
<div class='container'>
<div class='default selected'>
<h1>Page Title</h1>
<div class='yui-ge'> //for some reason, this tag remains hidden cause of the above CSS
//more div tags
</div>
</div>
//more HTML here
</div>
update
Look here: --LINK REMOVED--
Click the "Woot" tab.... no results are shown on the default woot tab - they remain hidden.
You have this CSS rule:
#main .woot > div:not(.sites):not(.default) {
display: none;
}
This rule applies to all DIVs inside the #main element, that do not have the classes sites or default and are children of a .woot element.
Your structure is:
<div id="main">
<div class="woot">
<div class="woot default selected">
<div class="yui-ge"> ... </div>
</div>
</div>
</div>
As you can see, the .yui-ge DIV does not have the class sites nor default and it is inside a .woot element. Therefore, it will be hidden.
The problem is that you have two DIVs in the ancestor chain that have the class woot.
If you hide an element, all it's child elements get hidden too.

Resources