Hongbin's Blog

vuePress-theme-reco Hongbin's Blog    2021
Hongbin's Blog Hongbin's Blog

Choose mode

  • dark
  • auto
  • light
GitHub
Category
  • article
  • note
  • tip
  • draft
  • log
  • recette
Tag
Home
TimeLine

Hongbin's Blog

13

Article

13

Tag

GitHub
Category
  • article
  • note
  • tip
  • draft
  • log
  • recette
Tag
Home
TimeLine
  • CSS - a dropdown menu with a triangle

    • Step 0. make a dropdown list
      • Step 1. attach a pseudo element to the menu
        • The full snippet of code

        CSS - a dropdown menu with a triangle

        vuePress-theme-reco Hongbin's Blog    2021

        CSS - a dropdown menu with a triangle


        Hongbin 2020-10-12 css

        # Summary

        A triange can be made by a element with the following style 
        	1. width:0
        	2. height:0
        	3. border-width
        			the value of it depends on the margin-top of dropdown
        			normally, half value of margin-top (caz you have top and bottom border)
        	4. border: solid transparent
        		transparent is needed for overlapping background-color taken from parent element
        	4. border-bottom-color
        	5. content (if it is a pseudo element)
        
        To make menu item look like centrally align, simply just use `padding`
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12

        # Notes

        So I saw a css effect and was wondering how that was made. It used around half an hour to identify that effect, just because I paid attention to a wrong html tag 😦

        The css effect I want to know is shown in the following picture.

        image

        The triange that the red arrow points to is the one I am taking about. Shortly speaking, position + pseudo-classes:hover + pseudo-elements:before plays the role (IDK why they use :after, it seems unnecessary).

        So how they do that?

        # Step 0. make a dropdown list

        First, you need a menu item or anything else to be a reference. Let's say, the menu. So, set that menu as position: relative; Then, surely we will have pseudo elements :before and :after as absolute position elements according to the menu, which appear when the pointer hovers onto.

        Now here is what we have by now.

        	<style>
        	html *{
        		font-size: 15px;
        		padding: 0;
        		margin: 0;
        	}
        	html{
        		background: grey;
        	}
        	.header-menu-item{
        		width: 10rem;
        		min-height: 1.5rem;
        		padding: 0.5rem;
        		text-align: center;
        		background: black;
        		color: white;
        		position: relative;
        	}
        	.header-menu-item ul{
        		display: none;
        	}
        	.header-menu-item:hover ul {
        		list-style: none;
        		color: black;
        		background: white;
        		position: absolute;
        		left: 25%;
        		margin-top: 1rem;
        		display: block;
        	}
        	.header-menu-item:hover ul li{
        		padding: 0.5rem 1rem;
        	}
        	</style>
        
        	<div class="header-menu-item">
        		<a>Header Item A</a>
        		<ul>
        			<li>option 1</li>
        			<li>option 2</li>
        		</ul>
        	</div>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42

        image

        # Step 1. attach a pseudo element to the menu

        Then, attach a :before same as what ul do. The code below is what I saw from the site and I extracted the attributes only needed for this effect.

        .header-menu-item:hover ul:before{
            content: " ";
            position: absolute;
        	bottom: 100%;
            left: 43%;
        	border: solid transparent;
            border-bottom-color: rgb(225, 225, 225);
            border-width: 0.5rem;
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9

        image

        This is kind of like a piece of magic code. The pseudo element is just an element with a bottom border and attached to the top of dropdown menu, so why is it a triange?

        After some attempts of changing the attributes, the theory behind magic is revealed.

        image

        What you can see in this picture is the :before element with width and height more than 0. Normally you will use border with a element has some size, then surely it is a border. But if the element has no size, it becomes a triange, and the direction of that triange is according to what attribute, such as border-top, border-bottom you use.

        So what does a "triangle" element contains?

        image

        The tiny content(I set w&h to 1px) is at the center of the element and the rest is the trianges/borders. And the way to adjust the size of triange is to use border-width.

        # The full snippet of code

        <style>
        html *{
        	font-size: 15px;
        	padding: 0;
        	margin: 0;
        }
        html{
        	background: grey;
        }
        .header-menu-item{
        	width: 10rem;
        	min-height: 1.5rem;
        	padding: 0.5rem;
        	text-align: center;
        	background: black;
        	color: white;
        	position: relative;
        }
        .header-menu-item ul{
        	display: none;
        }
        .header-menu-item:hover ul {
        	list-style: none;
        	color: black;
        	background: white;
        	position: absolute;
        	left: 25%;
        	margin-top: 1rem;
        	display: block;
        }
        .header-menu-item:hover ul li{
        	padding: 0.5rem 1rem;
        }
        .header-menu-item:hover ul:before{
            content: " ";
            position: absolute;
        	bottom: 100%;
            left: 43%;
        	border: solid transparent;
            border-bottom-color: rgb(225, 225, 225);
            border-width: 0.5rem;
        }
        </style>
        
        <div class="header-menu-item">
        	<a>Header Item A</a>
        	<ul>
        		<li>option 1</li>
        		<li>option 2</li>
        	</ul>
        </div>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51