How does changing the display attribute in the styling of an element hide/show it? - html

I'm following this tutorial on how to create a CSS dropdown menu. Currently the method stated does not use any JavaScript (only HTML and CSS). Here is the method suggested, excluding the color/background color/font/etc.
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
}
.dropdown-content a {
display: block;
}
.dropdown:hover .dropdown-content {
display: block;
}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
As you can see, the Dropdown button appears, and when one hovers over it, the list items are shown. The only styling applied when an element is hovered over is
.dropdown:hover .dropdown-content {
display: block;
}
How does this work? (the w3schools tutorial did not describe the reasoning behind the display styling)
When I ran the above snippet, I was expecting the list items to be shown inline and then, when the button is hovered over, to be shown as a block under the button (thus I was expecting the list items to never be hidden). What is making these list items hidden by default?
Furthermore, if I am applying the display: block styling on the div element (the one with the class dropdown), then how come when I hover over the empty space still physically under the button, however to the right of the list text, the display: block styling is undone (and the list items vanish)? I would expect the div element to take up an area in the shape of a rectangle (where even hovering over the white part of the rectangle would trigger :hover). *
* I may need to clarify this entire part of my question, please say so if I need to.

The .dropdown-content is hidden by default:
.dropdown-content {
display: none;
}
The later rule overrides that and shows the content when the pointer hovers over the parent .dropdown:
.dropdown:hover .dropdown-content {
display: block;
}
This rule applies to any .dropdown-content within a .dropdown that is in the hover state.
To answer the second question, it's because of the position: absolute that the white-space next to the child items don't maintain the hover state. See the snippet below, which includes outlines to show the boundaries of each element. As long as the pointer is within the blue (parent) box or the red (child) box, the hover state is maintained.
.dropdown {
position: relative;
display: inline-block;
outline: solid 1px blue;
}
.dropdown-content {
display: none;
position: absolute;
outline: solid 1px red;
}
.dropdown-content a {
display: block;
background: yellow;
}
.dropdown:hover .dropdown-content {
display: block;
}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>

Related

CSS-only dropdown menu works fine but not in Edge

I am working on a CSS-only dropdown menu. This is the code I am using now:
.show
{ display: none;
}
.hide:focus + .show
{display: block;
}
.hide:focus
{display: none;
}
#ddm
{display: none;
}
.hide:focus ~ #ddm
{display: block;
}
<body>
menumenu
<div id="ddm">items</div>
</body>
It works heartily in all browsers except Microsoft Edge. That browser only shows the menu for a fraction of a second. :( Does anyone possibly know what is happening here? And how I can fix this? I appreciate all the help. Thank you very much!
Kind regards,
George.
Updated Answer: As per comments, without using JavaScript or a checkbox technique and using the :focus pseudo class, you could wrap the menus in a button and use that as the initial focus trigger.
/* Menu styling for demo, change as needed */
#menu {
cursor: pointer;
padding: 0px;
border: 0;
background: none;
}
/* Hidden initially */
#ddm,
#hide {
display: none;
}
/* Prevent the 'show' element from triggering focus */
#show {
pointer-events: none;
}
/* Show elements as needed */
#menu:focus~#ddm,
#menu:focus #hide,
#menu:not(:focus) #show,
#hide:focus #show {
display: block;
}
/* Hide elements as needed */
#menu:focus #show,
#menu:not(:focus)~#hide,
#hide:focus #hide {
display: none;
}
<body>
<!-- New button element to wrap around the two menus -->
<button id="menu">
<!-- Numbers in text added just to demonstrate the difference -->
menu1
menu2
</button>
<div id="ddm">items</div>
</body>
Original Answer: Perhaps a simpler approach would fit your needs (unless you have a specific reason to use two menus that are hidden and shown). Just have one menu that is always shown, and toggle the items depending on its focus:
#ddm {
display: none;
}
.menu:focus~#ddm {
display: block;
}
<body>
menu
<div id="ddm">items</div>
</body>
I would still be using javascript or the checkbox method as they are more robust, but the following could work.
Use some creative positioning and the :target pseudo class, which selects the element referenced by href=#someId and then sibling selectors. Then the id for the burger menu is added to the show link href which is also better semantics. The hide/show buttons will need to be added after the menu element then repositioned with position:absolute.
/*Position everything relative to nav*/
nav {
position: relative;
padding-top: 1.25em;
}
/*Position our show/hide elements*/
.show,.hide {
position: absolute;
top: 0;
}
/*Hide burger and button */
#ddm, #ddm:not(:target) ~ .hide {
display: none;
}
/*Show Burger when show clicked*/
#ddm:target {
display: block;
}
/*HIde Burger when not show clicked*/
#ddm:target~.show {
display: none;
}
<body>
<!-- Nav Used For Positioning -->
<nav>
<div id="ddm">Burger</div>
Show Burger
Hide Burger
</nav>
</body>

Responsive dropdown navbar

I am doing a school project in which I'm not allowed to use Javascript or Bootstrap, and I cannot find a way to make a dropdown menu when the site is opened in smaller screens. Most guides and videos show using Bootstrap or JS and it has gotten me all confused, is it possible to do with just HTML and CSS?. Can anyone give me some quick tips or alternatives? Thank you beforehand!
Answer below using HTML and CSS only.
If my answer works, please check it as final answer and upvote it so other people with same problem will get help too. Cheers
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
<style>
/* Style The Dropdown Button */
.dropbtn {
cursor: pointer;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
padding: 12px;
text-decoration: none;
display: block;
}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
</style>

Using css/html dropdown as Mediawiki template

I am trying to use this dropdown as a Mediawiki template and allow for Mediawiki parameters in the URL creation (I.e. {{PAGENAME}}). Apparently, this type of html elements is not parsed. Trying $wgRawHtml = true; resulted in the template being displayed, but, apart from being a security risk, there was no way to have parsable elements. I did find this template but I could not figure out how do adapt it to work with the styling of the dropdown in question.
In the page MediaWiki:Common.css (or MediaWiki:Skinname.css, if you only want it for a certain skin), add your desired CSS:
/* Dropdown Button */
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #ddd;}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {display: block;}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {background-color: #3e8e41;}
If everything in the template is going to be an internal link, make this your template:
<div class="dropdown">
<div class="dropbtn">{{{title|Dropdown}}}</div>
<div class="dropdown-content"><!--
-->{{#if:{{{1|}}}|[[{{{1}}}]]}}<!--
-->{{#if:{{{2|}}}|[[{{{2}}}]]}}<!--
-->{{#if:{{{3|}}}|[[{{{3}}}]]}}<!--
-->{{#if:{{{4|}}}|[[{{{4}}}]]}}<!--
-->{{#if:{{{5|}}}|[[{{{5}}}]]}}<!--
</div>
</div>
And then invoke it like this:
{{dropdown|Foo|Bar|Baz}}
And it will make a dropdown with links to the pages Foo, Bar, and Baz on your wiki.
If you have to support external links or plaintext, use this instead:
<div class="dropdown">
<div class="dropbtn">{{{title|Dropdown}}}</div>
<div class="dropdown-content plainlinks"><!--
-->{{#if:{{{1|}}}|<span>{{{1}}}</span>}}<!--
-->{{#if:{{{2|}}}|<span>{{{2}}}</span>}}<!--
-->{{#if:{{{3|}}}|<span>{{{3}}}</span>}}<!--
-->{{#if:{{{4|}}}|<span>{{{4}}}</span>}}<!--
-->{{#if:{{{5|}}}|<span>{{{5}}}</span>}}<!--
--></div>
</div>
Change the as in the CSS to spans, and add a rule to make sure they are black instead of blue:
/* Links inside the dropdown */
.dropdown-content span {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content span:hover {background-color: #ddd;}
.dropdown-content a, .dropdown-content a:hover{
color: black;
text-decoration: none;
}
And then, you can invoke it like
{{dropdown|[[Foo]]|[https://www.google.com/ Google]|Plain text}}
and it has a link to the page Foo, a link to Google, and a plain-text menu item.
Note: If a parameter contains an equals sign (=), you need to specify all the parameter names, like this:
{{dropdown|1=[https://duckduckgo.com/?q=foo&ia=web Search for Foo]|2=Bar}}
See also: Passing an equal sign ('=') to a parameter in a MediaWiki template
So I tried to use this, and I'm having an issue where the rest of the page content that is after the dropdown, is in the dropdown itself. IT doesn't look like any of the parameters aren't closed, so I'm not sure why it's doing that. Using MW1.32

Hover is not displaying a dropdown menu

I'm trying to make a drop down menu but the hover is not producing the desired display effect. I just want the drop down menu to display when the mouse hovers over the list element. I'm new to HTML and CSS, so I can't pinpoint my error.
The relevant HTML:
#strip{
width: 950px;
height: 28px;
background-color: #2c276d;
font-size: 10pt;
}
.strip{
margin:0;
padding: 0;
}
.strip li{
list-style-type: none;
float: left;
}
.strip li a {
color: white;
text-decoration: none;
display: block;
text-align: center;
width:140px;
height:23px;
padding-top:5px;
border-right: 1px solid #FFFFFF;
}
.strip li.shrt a{
width: 145px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropcmpy {
display: none;
position: absolute;
background-color: #2c276d;
font-size: 10pt;
width: 145px;
}
.dropcmpy a {
color: white;
display: block;
text-decoration: none;
padding: 5px;
border-top: 1px solid #FFFFFF;
}
.strip li a:hover{
background-color: #28A2D5;
}
li.shrt:hover .dropcmpy {
display: block;
}
<div id="main">
<div id="strip">
<ul class="strip">
<li class="shrt">Com</li>
</ul>
</div>
<div class="dropcmpy">
Key
Ad
Fac
Car
FAQ
</div>
</div>
No matter how I format that last piece of CSS, it doesn't produce a drop down menu, unless I do
#main:hover .dropcmpy {
display: block;
}
or give the first div a class, and then use that. Otherwise the dropdown menu will not appear. This presents the issue that the entire strip will then produce the menu, while I want only the shrt to.
As john stated, selector .class1 .class2 is targeting an element with class="class2" that is a child of an element with class="class1".
which means you need to put the dropdown menu INSIDE the element, thats supposed to show the dropdown when hovered.
Usuall way is using another list inside the button, for example
<div id="main">
<div id="strip">
<ul class="strip">
<li class="shrt">
Com
<ul class="dropcmpy">
<li>Key</li>
<li>Ad</li>
<li>Fac</li>
<li>Car</li>
<li>FAQ</li>
</ul>
</li>
</ul>
</div>
</div>
and css
.dropcmpy {display: none;}
.shrt:hover .dropcmpy {display: block;}
That should do it, hope it was helpful :).
In order to show an object on hover with css, that object must be the sibling or child of the thing being hovered (As there are no parent selectors). This is not the case in your code.
So you have a few options:
Make div.dropcmpy a child of li.shrt. (As in Teuta Koraqi's answer)
Hack. Use an empty pseudo element (.dropcmpy::before) and absolutely position it over li.shrt, then use that as the hover element.
Use javascript
I don't know what the structure of your page is so can't say which of these would be best for you. The first is certainly the cleanest if you can manage it.
The problem is with inheritance. The last block that you are trying to use is looking for a .dropcmpy element that is a child of .shrt (which obviously doesn't exist). The reason the alternative works is because .dropcmpy is a child of #main.
I don't see any issue with using #main as the hover listener, since everything related to the dropdown is contained in it anyways.
After a reminder from #JohnCH, I realized you could do a sibling selector like this to get the functionality I think you want.
#strip:hover+.dropcmpy {
display: block;
}

One-level drop-down menu from ul list styled with css possible?

I have a list of items of which only the first is visible and on list hover shows all items with side effect of changing the position of surrounding content. How to evade this unwanted effect?
Here is an example list:
http://jsfiddle.net/dsbonev/z8Sjy/
All examples that I checked for styling menus have a two-level structure (parent -> children). On parent hover children are shown. But I don't have a parent to hover onto nor I want to promote one of the children as a parent by moving it out of the list and thus breaking the semantic of the markup.
Figured it out! This is what I wanted:
http://jsfiddle.net/z8Sjy/
I accept comments with shortcomings or improvements of this method.
HTML
<div class="list-wrapper">
<ul class="items">
<li>stackoverflow</li>
<li>superuser</li>
<li>serverfault</li>
</ul>
</div>
CSS
.list-wrapper, .items {
display: inline-block;
}
.list-wrapper {
position: relative;
background-color: blue;
height: 1em;
}
.items {
position: absolute;
background-color: red;
}
.items > li:not(:first-child) {
display: none;
}
.items:hover > li:not(:first-child) {
display: block;
}
You could position the list absolutely and then add padding to the paragraph to compensate.
http://jsfiddle.net/z8Sjy/2/
Instead of using display: none & display: block use visibility: hidden & visibility: visible. That way they take up the space in the HTML document, but are not shown:
Working example: http://jsfiddle.net/z8Sjy/3/
Edit
The following CSS would be more cross-browser compatable for showing / hiding "not first-child" elements as the selector :not is actually CSS3.
.items > li:first-child ~ li {
display: none;
}
.items:hover > li:first-child ~ li {
display: block;
}