I'm trying to make a vertical navigation that is in a skewed parent div. My goal is to have all the list items follow the same path as the edge of the parent div, I'm not quite certain how to go about it.
I typed up a sample in codepen showing the default behaviour.
http://codepen.io/anon/pen/YWYQmd
<div class="parent">
<ul class="navigation">
<li><a>text</a></li>
<li><a>text</a></li>
<li><a>menu</a>
<ul class="submenu">
<li><a>text</a></li>
<li><a>text</a></li>
<li><a>menu</a>
<ul class="submenu">
<li><a>text</a></li>
<li><a>text</a></li>
</ul>
</li>
</ul>
</li>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
</div>
.parent {
background: rgba(123,23,55,0.2);
width: 500px;
text-align: right;
transform: skew(-20deg);
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
transform: skew(20deg);
}
.submenu{
transform: skew(-20deg);
}
Any tips to make it line up like I want? Thanks!
The issue comes from 'unskewing' the li elements: in the case the li element has another ul, then the whole block becomes unskewed.
What you need to do is 'unskew' only the content of the li, not the li itself. Assuming all your text will be within an a tag, then just replace your 'unskew' with:
li a{
display: inline-block;
transform: skew(20deg);
}
See result here: http://codepen.io/anon/pen/VjyzYq
Related
I was trying to make dropdown menu using only css, however it doesn't work in my case.
It's kinda working when I don't put position:absolute at .dropdown_content in CSS, but even when I do that, dropdown doesn't work.
HTML:
<nav>
<ul>
<div class="dropdown">
<li>Game order</li>
<div class="dropdown_content">
Half-life
Half-life 2
Half-life EP1
</div>
</div>
<li>Portal series</li>
<li>Half Life Alyx</li>
</ul>
</nav>
CSS:
.dropdown {
position:relative;
display:inline-block;
}
.dropdown_content {
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
min-width: 160px;
display:none;
}
.dropdown_content a {
color:white;
text-decoration: none;
display:block;
padding: 12px 16px;
}
}
.dropdown:hover .dropdown_content {
display: block;
}
To keep things simple, I have reduced your code to a bare minimum.
I'm not sure exactly how you want it to look, but here's a possible solution.
When making css only menu's I try to stick to a nested list of <ul> and <li>'s.
This makes it clearer to read, and keeps the semantics in order.
Ther is no need for container divs within. (like the <div class="dropdown_content"> in your code)
The HTML is a nested list. Initially we hide the nested ul, and only show it when it's parent is hovered over. By using .dropDown li:hover>ul you only target the ul that is DIRECTLY under the hovered li. That way you dan nest as deep as you want.
.dropDown ul {
display: none;
position: absolute;
background: white;
border: 1px solid red;
}
.dropDown li:hover>ul{
display: block;
}
<ul class="dropDown">
<li>Game order
<ul>
<li>Half-life</li>
<li>Half-life 2</li>
<li>Half-life EP1</li>
</ul>
</li>
<li>Portal series</li>
<li>Half Life Alyx</li>
<li>deeper nesting
<ul>
<li>level 1</li>
<li>more here
<ul>
<li>level 2</li>
<li>more here
<ul>
<li>level 3</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
I'm working in a legacy environment where it's too challenging to change the HTML rendered to a page. Instead, I'm looking for a CSS solution for a situation where only the child of the list item has an existing class I can use:
HTML structure
<ul>
<li><div class="myobject">A</div></li>
<li><div class="myobject">A</div></li>
<li><div class="myobject">A</div></li>
</ul>
<ul>
<li><div class="myobject floated">B</div></li>
<li><div class="myobject floated">B</div></li>
<li><div class="myobject floated">B</div></li>
</ul>
Desired output
A
A
A
BBB
I've tried
li {
display:inline-block;
}
li > div {
display:block;
}
li > div.floated {
display:inline-block;
float:left;
}
Updated:
I found a CSS-only solution that works in my particular case (below)
I was able to solve my particular situation using the div to provide the bullet by default, and the extra class to take it away.
ul {
list-style:none;
margin:0;
padding:0
}
li {
display:inline;
}
li .myobject::before { /* add the new bullet point */
display: inline-block;
content: '';
-webkit-border-radius: 50%;
border-radius: 50%;
height: 0.25em;
width: 0.25em;
margin-right: 0.5rem;
background-color: #000;
position: relative;
top: -0.2em;
}
li .floated {
display:inline-block;
}
li .floated::before {
height:0;
width:0;
background-color:transparent;
margin-right:0;
}
Lately in 2017, in the Selectors Level 4 they have introduced :has() selector which will be able to select an element based on its children, but it hasn't been approved yet, and it's not yet supported in any browser.
Assumption:
If it was available it would be very easy by using:
li:has(>div.floated) {
display:inline-block;
float:left;
}
JS/jQuery:
But unfortunately, it's not supported yet by any browser, it's however used by jquery or by Javascript .querySelector() and you can use it like this:
$('li:has(>div.floated)').css({
"display": "inline-block",
"float": "left"
});
$('li:has(>div.floated)').css({
"display": "inline-block",
"float": "left"
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<div class="myobject">A</div>
</li>
<li>
<div class="myobject">A</div>
</li>
<li>
<div class="myobject">A</div>
</li>
</ul>
<ul>
<li>
<div class="myobject floated">B</div>
</li>
<li>
<div class="myobject floated">B</div>
</li>
<li>
<div class="myobject floated">B</div>
</li>
</ul>
Another option:
Another option is to use another class with the li itself instead of its div:
.myLi {
display: inline-block;
float: left;
}
Not sure about your legacy environment but You could achieve this by using nth-child() selector as shown below. Ofcourse this will only work if you do have access to the mentioned CSS selector.
ul:nth-child(2) {
list-style: none;
padding: 0;
margin: 0;
}
ul:nth-child(2) li {
display: inline-block;
}
<ul>
<li><div class="myobject">A</div></li>
<li><div class="myobject">A</div></li>
<li><div class="myobject">A</div></li>
</ul>
<ul>
<li><div class="myobject floated">B</div></li>
<li><div class="myobject floated">B</div></li>
<li><div class="myobject floated">B</div></li>
</ul>
I'm still trying to get the hang of <details> and I've run into a snag that I know has a very obvious answer, but... it's late, I'm stupid, and I cannot figure it out.
How do I prevent a div from moving to accommodate an expanded details tag, like in the instance of the red div in the following snippet?
.test {
background: red;
height: 50px;
width: 50px;
}
<details>
<summary>Summary Test</summary>
<ul>
<li>Thing #1</li>
<li>Thing #1</li>
<li>Thing #1</li>
</ul>
</details>
<div class="test">
Test
</div>
Based on the problem statement, this will do the job.
.test {
background: red;
height: 50px;
width: 50px;
top:26px;
position:absolute;
z-index:-1;
}
position:absolute - Will fix it to the parent (in the snippet the parent is body element), you can adjust the position.
top:26px; - I am setting the position from the top of the parent to 26px, you can also set left, right, bottom
z-index:-1 - If you want the absolute element to be behind the dropdown, you need to set this property and the dropdown will show above the div with class test
.test {
background: red;
height: 50px;
width: 50px;
top: 26px;
position: absolute;
z-index: -1;
}
<details>
<summary>Summary Test</summary>
<ul>
<li>Thing #1</li>
<li>Thing #1</li>
<li>Thing #1</li>
</ul>
</details>
<div class="test">
Test
</div>
Like a folding menu, you can set the folding part in absolute position
.test {
background: red;
height: 50px;
width: 50px;
}
details {
position:relative;/* reference for absolute child */
background:tomato;
}
summary + ul {
margin:0;/* reset margin to stick to summary*/
position:absolute;/* take it off the flow to not disturb the layout */
background:inherit;/* make sure background is there too and .test hidden underneath*/
}
<details>
<summary>Summary Test</summary>
<ul>
<li>Thing #1</li>
<li>Thing #1</li>
<li>Thing #1</li>
</ul>
</details>
<div class="test">
Test
</div>
or set an height to details and let overflow be visible
.test {
background: red;
height: 50px;
width: 50px;
}
details {
height:1.4em;
position:relative;/* keep it on top */
background:tomato;
}
summary + ul {
margin:0;
background:inherit;
}
<details>
<summary>Summary Test</summary>
<ul>
<li>Thing #1</li>
<li>Thing #1</li>
<li>Thing #1</li>
</ul>
</details>
<div class="test">
Test
</div>
Question: How do I get this to work for tabbing, using CSS only? (Tabbing already works).
#menu:before {
content:"Menu \25bc";
font-weight:bold;
width:100%;
}
#menu:hover:before {
content:"Menu \25b2";
}
#menu li {
position:absolute;
left:-9999px;
}
#menu:hover li {
position:relative;
left:0;
}
<html>
<title>Test</title>
<body>
<header>
Link to homepage
</header>
<nav>
<ul id="menu">
<li>Menu item 1</li>
<li>Menu item 2</li>
</ul>
</nav>
<main>
<p>Other text with maybe a link here.</p>
</main>
</body>
</html>
EDIT: Original question follows.
I have a menu:
<ul id="menu">
<li>Menu item 1</li>
<li>Menu item 2</li>
</ul>
However, I want to hide it at a narrow page width, so I apply the following CSS:
#media (max-width: 768px) {
#menu:before {
content:"Menu \25bc";
}
#menu:hover:before {
content:"Menu \25b2";
}
#menu a {
position:absolute;
left:-9999px;
}
#menu:hover a {
position:relative;
left:0px;
}
}
This hides the menu, adds the word "Menu" in it's place, with a down or up arrow, depending on the hover state, which also shows the menu when you hover over it.
The problem is that, while :hover works just fine, I cannot get both to show by tabbing to one of the tags, using the :focus pseudo class. (Alas, :root will not work like other pseudo classes, so something like #menu a:focus:root #menu a { position:relative; left:0; } won't work, as far as I can see).
Does anyone have any ideas as to how I could approach this, using only CSS? Or have I dug myself into a hole?
Based on OP comment below:
I'm happy to change the HTML, but how would :target work here?
here is a snippet with :target
nav {
height: 0;
overflow: hidden;
position: relative;
}
nav:target {
height: auto;
}
nav + div a:before {
content: "Menu \25bc";
font-weight: bold;
width: 100%;
}
nav:target + div a:before {
content: "Menu \25b2";
}
nav:target + div .open,
nav + div .close {
display: none;
}
nav:target + div .close,
nav + div .open {
display: block;
position: absolute;
top: 0
}
<nav id="menu">
<ul>
<li>Menu item 1
</li>
<li>Menu item 2
</li>
</ul>
</nav>
<div>
<a class="open" href="#menu"></a>
<a class="close" href="#"></a>
</div>
When trying to add an box with content inside it on a menu on a hover "drop down menu", it does something like this:
(source: gyazo.com)
I want the drop down to popup when I hover on the categories menu item.
This is the code I used for it:
<div class="secondheader">
<div class="container">
<div class="span12">
<ul class="nav6">
<li>Home</li>
<li class="dropdown1">Categories </li>
<li>Buy</li>
<li>Sell</li>
<li>Forums</li>
<li>Contact</li>
<li>item 1</li>
<li>Forums</li>
<li>Contact</li>
<li>item 1</li>
</ul>
</div>
</div>
</div>
</div>
The CSS:
.secondheader {
background-image: url("../img/second.png");
width: 100%;
height: 66px;
border-bottom: solid 6px #f0e8ce;
}
.nav6 {
list-style: none;
font-family: 'Dosis', sans-serif;
float: left
font-size: 20px;
margin-top: 13px;
margin-left: -35px;
}
.nav6 li {
display: inline;
margin: 0px;
font-size: 18px;
font-family: 'Dosis', sans-serif;
float: left;
margin-top: 10px;
}
.nav6 a {
color: #7d7253;
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
padding-right: 20px;
}
.nav6 a:hover {
background-image: url("../img/hoverbg.png");
color: #53410f;
text-decoration: none;
}
I've tried using tutorials but I don't really understand on how to make the same thing for my layout I mean it has different ways and classes.
Do you want something like http://jsfiddle.net/b76Qc/?
Edit:
In your case the submenu is horizontal because you use descendant selectors instead of child selectors:
replace .nav6 li with .nav6>li and .nav6 li ul with .nav6>li>ul
See my jsfiddle if you want the complete code.
Edit 2:
If you want each element to have a different background,
<li class="dropdown1">Categories
<ul>
<li style="background:red">Buy</li>
<li style="background:blue">Sell</li>
<li style="background:green">Forums</li>
...
</ul>
</li>
But can you provide a link to your site instead of images? The square shown in http://gyazo.com/35835f003d0d8b776248196632cc1d4a.png is weird, but I can't know what's happening just with images...
Edit 3:
You have to change
.nav6 a {
color: #7D7253;
padding: 20px;
}
into
.nav6>li>a {
padding: 20px;
}
.nav6 a {
color: #7D7253;
}
And
.nav6 a:hover {
background-image: url("../img/hoverbg.png");
color: #53410F;
text-decoration: none;
}
into
.nav6 a:hover {
color: #53410F;
text-decoration: none;
}
.nav6 > li > a:hover {
background-image: url("../img/hoverbg.png");
}
Edit 4:
Sorry I didn't explain why I was telling you to use selectors with >, I thought you knew it.
Your html is like this:
<ul class="nav6">
<li>Home</li>
<li class="dropdown1">Categories
<ul>
<li>Buy</li>
<li>Sell</li>
<li>Forums</li>
<li>Contact</li>
<li>item 1</li>
<li>Forums</li>
<li>Contact</li>
<li>item 1</li>
</ul>
</li>
</ul>
If you use .nav6 a, the style will be applied to all <a> inside .nav6. That's a descendant selector.
Then, this will be applied both to menu's links and submenu's links:
<ul class="nav6">
<li>Home</li>
<li class="dropdown1">Categories
<ul>
<li>Buy</li>
<li>Sell</li>
...
</ul>
</li>
</ul>
But if you use a child selector like .nav6>li>a, the style is applied only to the links which are childs of a <li> which is a child of .nav6 (only menu's links). This way we can set which styles we want to apply to all links and which to menu's links:
<ul class="nav6">
<li>Home</li>
<li class="dropdown1">Categories
<ul>
<li>Buy</li>
<li>Sell</li>
...
</ul>
</li>
</ul>
Edit 5:
To fix the problem with backgrounds,
change
.nav6 a:hover {
color: #53410F;
text-decoration: none;
}
to
.nav6>li:hover>a, .nav6 .dropdown1 li:hover>a {
color: #53410F;
text-decoration: none;
}
and
.nav6 > li > a:hover
background-image: url("../img/hoverbg.png");
}
to
.nav6>li:hover>a {
background-image: url("../img/hoverbg.png");
}
To show you how little code is actualy required to make this work i set up a small example here: http://jsfiddle.net/fS5WV/
I put the explanations in the css.
The key lies in nesting the menu's properly, and giving the submenus a position absolute to prevent them from pushing the content down.
I hope it makes sense. Feel free to ask if you need further explanation.