I build HTML/CSS/JS menu and want to align arrow to the right to point that this element is submenu.
My problem that in Firefox triangle ("▶" sign) shown on next line instead of current line...
Chromium shown both cases fine.
There are bugs in BTS that similar to my situation:
https://bugzilla.mozilla.org/show_bug.cgi?id=488725
I try 2 strategy, this my HTML structure:
<div class="name1">Submenu 1<span class="sub">▶</span></div>
Item 1
Item 2
<div class="name2">Submenu 2</div>
Item 1
Item 2
and this my CSS which shown issue:
a, .name1, .name2 {
display: block;
white-space: nowrap;
}
.name1 > .sub {
float: right;
}
.name2:after {
content: "▶";
float: right;
}
JS Fiddle for playground.
I remember I read code where margin-right: -16px or similar used with background image or something else to make such design but I can't remember exactly how.
What workaround possible?
UPDATE I make more complete example, HTML:
<div class="container">
Top level menu
<div class="box">
<div class="name1">Very long submenu 1<span class="sub">▶</span></div>
Item 1 1 1
Item 2
<div class="name2">Very long submenu 2</div>
Item 1
Item 2
</div>
</div>
CSS:
a { border: green 1px dotted; margin: 2px; }
a, .name1, .name2 {
display: block;
white-space: nowrap;
}
.name1 > .sub {
display: inline-block;
float: right;
}
.name2:after {
content: "▶";
float: right;
}
.container {
display: inline-block;
background: gold;
position: relative;
}
.box { display: none; }
.container:hover > .box {
display: block;
position: absolute;
top: 100%;
}
getting rid of "white-space: nowrap" helps
Finally I solve problem:
<div class="container">
Top level menu (hover on me)
<div class="box">
<div class="submenu">
<div class="name">Long submenu 1</div>
<div class="box">
Item 1
Item 2
</div>
</div>
Item 1 1 1
Item 2
<div class="submenu">
<div class="name">Very long submenu 2</div>
<div class="box">
Item 1
Item 2
Item 3
</div>
</div>
Item 1
Item 2
</div>
</div>
and:
.container {
display: inline-block;
background: gold;
position: relative;
}
.box { display: none; }
.container:hover > .box {
display: block;
position: absolute;
top: 100%;
}
.container .submenu {
position: relative;
}
.container .submenu:hover > .box {
display: block;
position: absolute;
top: 0;
left: 100%;
}
a, .name {
white-space: nowrap;
display: block;
}
.name {
padding-right: 1.2em;
position: relative;
}
.name:after {
content: "▶";
position: absolute;
top: 0;
left: 100%;
margin-left: -1em;
}
Essential part is to make element with triangle as block and position: relative and reserve space for triangle by padding-right: -1.2em and position triangle by position: absolute after element and move back triangle by margin-left: -1em.
Related
I am trying to style - on one line - a group of buttons on the left, a navigation list in the middle, and a group of buttons on the right. I have grouped the navigation buttons for when the layout should change. Question is how to get the navigation structure on the same line in the center of the parent element?
I have made both overarching div elements into "display: inline" elements, and also the navigation.
Do I need to use absolute positioning of the nav for this to work? Why?
How can I center the nav horizontally?
My HTML:
// you need to have font smoothing on to avoid blurred and jagged lines
html{
background-color: rgb(235, 235, 235);
}
#main_body{
width: 1200px;
margin: auto;
background-color: white;
}
// first line header styling
#header_topnav{
width: 96%;
height: fit-content;
}
// button div, navigation and button div
.topnav_button{
width: 45px;
height: 35px;
margin-top: 18px;
margin-bottom: 10px;
}
// make div inline element to get it on one line
#left_buttons{
display: inline;
position: relative;
}
// make div inline element to get it on one line
// no other way than to go with left or margin
#right_buttons{
display: inline;
position: relative;
margin-left: 87.5%;
// left: 86.5%;
}
// vertical centering
ul {
margin: auto;
}
// for horizontal nav menu
li {
display: inline;
float: left;
margin-left: 10px;
}
// display block so clickable area is larger
li a {
display: block;
}
// how do you center this horizontally?
// do I have to make position absolute? can't I keep it in between the button sections?
#top_navmenu {
position: absolute;
display: inline;
margin-top: 28px;
}
<div id="main_body">
<header>
<section id="header_topnav">
<div id="left_buttons">
<button class="topnav_button"></button>
<button class="topnav_button"></button>
</div>
<nav id="top_navmenu">
<ul>
<li><a>F+</a></li>
<li><a>POLITIK</a></li>
</ul>
</nav>
<div id="right_buttons">
<button class="topnav_button"></button>
</div>
</section>
</header>
</div>
You don't need to use position: absolute. You can achieve this with flexbox.
Just add display:flex on the wrapper ( #header_topnav ) and flex-grow: 1 on the middle menu. This way the menu will occupy all the available space between the left and right buttons.
Also when sharing code here on SO please be sure you share valid code.
HTML code is missing some closing tags
// is not a valid comment in CSS. Use /* comment */ instead.
See below
html {
background-color: rgb(235, 235, 235);
}
#main_body {
width: 100%;
margin: auto;
background-color: white;
}
#header_topnav {
height: fit-content;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.topnav_button {
width: 45px;
height: 35px;
margin-top: 18px;
margin-bottom: 10px;
}
#left_buttons {
display: inline;
position: relative;
}
#right_buttons {
position: relative;
}
ul {
margin: auto;
display: flex;
flex-direction: row;
}
li {
margin-left: 10px;
}
li a {
display: block;
}
#top_navmenu {
margin-top: 28px;
flex-grow: 1;
display: flex;
align-items: center;
}
<div id="main_body">
<header>
<section id="header_topnav">
<div id="left_buttons">
<button class="topnav_button"></button>
<button class="topnav_button"></button>
</div>
<nav id="top_navmenu">
<ul>
<li><a>F+</a></li>
<li><a>POLITIK</a></li>
</ul>
</nav>
<div id="right_buttons">
<button class="topnav_button"></button>
</div>
</section>
</header>
</div>
Is it possible to achieve something like above image?
So far I have tried following Code.
.greyParent {
height: 19px;
border-radius: 7px;
background: rgb(196, 196, 196);
}
.greyParent > .activeSlide {
background: rgb(0, 97, 188);
border-radius: 7px;
border-right: 1px solid #fff;
float: left;
width: 20%;
height: 19px;
position: absolute;
}
.greyParent > .activeSlide:first-child {
left: 0%;
z-index: 5;
}
.greyParent > .activeSlide + .activeSlide {
left: 16%;
z-index: 4;
}
<div class="col-xs-4 col-sm-2 col-md-2">
<span class="slideNo">1/5</span>
</div>
<div class="col-xs-8 col-sm-10 col-xs-9 progressImage">
<div class="greyParent">
<div class="activeSlide">
</div>
<div class="activeSlide">
</div>
</div>
</div>
I need to append .activeSlide div tag depending upon tab. Problem I am facing is as I append 5 .activeSlide div tags for fifth slide its not occupying entire parent div tag i.e div.greyParent. I understand that since i am doing position absolute and trying to move divs towards right, This is happening. But since i need to highlight the border of each partition i had to use position absolute. Can someone help me on this? Is there any solution for this?
You can use :before and :after pseudo elements to create this shape.
Draw circle of equal width and height on left/right corners of each list item respectively.
Add box-shadow of 1px or 2px to create border-effect between cells.
Output Image:
* {box-sizing: border-box;}
ul {
display: flex;
list-style: none;
padding: 0;
margin: 20px;
}
ul li {
position: relative;
background: gray;
height: 16px;
width: 60px;
}
ul li:before,
ul li:after {
box-shadow: 2px 0 0 #fff;
border-radius: 100%;
position: absolute;
background: gray;
height: 16px;
content: '';
width: 16px;
left: -8px;
top: 0;
}
ul li:first-child:before {
box-shadow: none;
}
ul li:after {
right: -8px;
left: auto;
}
ul li.active,
ul li.active:before,
ul li.active:after {
background: blue;
z-index: 1;
}
<ul>
<li class="active"></li>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
You can simply overlap the elements and give them the right width to make sure that they will be in the right place. You should also play with the left property to make them appear where you want.
The key should be in the properties you can see here:
.greyParent > div{
width: 25%;
}
.greyParent > div:nth-child(1){
left:0%;
width: 20%;
}
.greyParent > div:nth-child(2){
left:15%;
}
I have created this small jsfiddle which you can see as an example of what I mean
Try this, it's good ))
<div class="container">
<div class="title">
1/5
</div>
<div class="progress">
<span class="active"></span><span class="active"></span><span></span><span></span><span></span>
</div>
</div>
.container {
display: flex;
}
.container .title {
padding-right: 20px;
}
.container .progress {
display: flex;
width: 250px;
}
.container .progress span {
display: block;
height: 15px;
width: 20%;
background: gray;
border: solid 1px #fff;
border-radius: 7px;
margin-right: -15px;
}
.container .progress span.active {
background: blue;
}
.container .progress span:nth-child(1) {
z-index: 40;
}
.container .progress span:nth-child(2) {
z-index: 35;
}
.container .progress span:nth-child(3) {
z-index: 25;
}
.container .progress span:nth-child(4) {
z-index: 10;
}
JSfiddle example https://jsfiddle.net/5ph3uk94/
Why don't you just use 2 blue elements and 3 grey elements, instead of one big grey parent ?
<div class="col-xs-4 col-sm-2 col-md-2">
<span class="slideNo">1/5</span>
</div>
<div class="col-xs-8 col-sm-10 col-xs-9 progressImage">
<div class="parent">
<div class="activeSlide"></div>
<div class="activeSlide"></div>
<div class="diabledSlide"></div>
<div class="diabledSlide"></div>
<div class="diabledSlide"></div>
</div>
</div>
Practicing on anchor tags and drop down menu. In the following code, the dropdown is not working. Don't know why. The div containing text "This is dropdown menu" should appear exactly below the div containing text "This is text. Its in center" whenever the later is hovered upon. Both the divs are of same width.
html,body {
margin: 0px;
height: 100%;
/* [disabled]width: 100%; */
left: 0px;
top: 0px;
background-color: rgba(255,255,255,1);
}
.wrapper {
text-align: center;
margin-top: 0;
margin-left: auto;
height: 100%;
max-width: 960px;
background-color: rgba(0,0,0,1);
margin-right: auto;
position: relative;
}
.link1 {
height: auto;
width: 50%;
color: rgba(255,255,255,1);
margin-right: auto;
margin-left: auto;
background-color: rgba(204,204,204,1);
}
.link1 a {
text-decoration: none;
display: block;
}
.link1 a:hover {
text-decoration: underline;
background-color: rgba(255,0,0,1);
}
.link1 a:hover .dropdown {
display: block;
}
.dropdown
{
height: 25%;
width: 50%;
background-color: rgba(204,204,204,1);
margin-right: auto;
margin-left: auto;
text-align: center;
display: none;
}
<div class="wrapper">
<div class="link1">
This is text. Its in center
</div>
<div class="dropdown">This is dropdown menu</div>
</div>
Your css selector .link1 a:hover .dropdown selects the element with the class dropdown which has to be inside of an a element in a hover state (a:hover), which is inside an element with a class of link1.
This doesn't match your html markup.
To get it work, you can change your html to this:
<div class="wrapper">
<div class="link1">
<a href="http://www.hotmail.com">
This is text. Its in center
<div class="dropdown">This is dropdown menu</div>
</a>
</div>
</div>
Hope it helped.
Lexith is partly right, you need to add the dropdown within the container div, you can then select the sibling of the hovered a link.
Like so;
CSS -
.link1 a:hover + .dropdown {
display: block;
}
HTML -
<div class="link1">
This is text. Its in center
<div class="dropdown">This is dropdown menu</div>
</div>
CSS update -
This allows the dropdown to stay open when hovering on it
.dropdown:hover,
.link1 a:hover + .dropdown {
display: block;
}
This means it doesnt have any of the a tag styling. View my code pen
I have 3 boxes which look like the one in the example. I want to apply a certain style on the non-hovered boxes when a user hovers over a certain box (The boxes are always siblings).
Here is how it should work -
Hover over Box 1 - Box 2 and Box 3 should be greyed
Hover over Box 2 - Box 1 and 3 should be greyed
Hover over Box 3 - Box 1 and 2 should be greyed
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.test:hover ~ .test {
width: 100px;
background-color: #ddd;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
<div class="test">
Box 1
</div>
<div class="test">
Box 2
</div>
<div class="test">
Box 3
</div>
I can get it working for Box 1. Can somebody help me how I can do it elegantly for Box 2 and 3.
Note: No jQuery or Javascript should be used (which would be a cakewalk in this case).
You can not select “upwards” with current CSS selectors, so 2 and 3 are not possible – not directly. You could put all elements into a common container element, and when that is hovered make all boxes gray, and then the actual box hovered blue again:
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.container:hover .test {
background:#ddd;
}
.container .test:hover {
background-color: #009AFD;
}
<div class="container">
<div class="test">Box 1</div>
<div class="test">Box 2</div>
<div class="test">Box 3</div>
</div>
(No need btw. to repeat all those properties that stay the same in the hovered state.)
This however will also apply the hover effect when you are not directly hovering one of the boxes, but also when the container element is hovered in the margin between the boxes – so when in between the boxes, all three of them will become gray.
To fight that effect, you need to get a little creative: By not having the boxes laid out in normal flow, but positioning them absolutely instead, you can make the container element take up no space at all, so it won’t be hovered in the “margins” between the boxes. Hovering the boxes themselves however still triggers :hover for the container element, since the boxes are its children and therefor hovering them means hovering the parent element as well, even if the parent element is not “present” in that space where the mouse cursor is hovering over.
.container {
position: relative;
}
.test {
position: absolute;
top: 0;
left: 0;
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
text-align: center;
}
#box2 {
left: 110px;
}
#box3 {
left: 220px;
}
.container:hover .test {
background: #ddd;
}
.container .test:hover {
background-color: #009AFD;
}
<div class="container">
<div class="test" id="box1">Box 1</div>
<div class="test" id="box2">Box 2</div>
<div class="test" id="box3">Box 3</div>
</div>
Of course then you might have to use some additional trickery to keep following elements in normal flow at the same positions they would take, had the absolute positioning not taken the boxes out of flow (like giving the next element a margin-top or something).
And of course the whole thing only works this “simple”, because you want the color for the siblings of the hovered boxes to be the same. Would you wish for different colors for them, then additional trickery of sorts might be needed.
This will do it:
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.parent:hover > div {
width: 100px;
background-color: #ddd;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.parent:hover > div:hover {
background-color: #009AFD;
}
<div class="parent">
<div class="test">Box 1</div>
<div class="test">Box 2</div>
<div class="test">Box 3</div>
</div>
Enclose the divs in a parent div. Use this selector to change all the children: .parent:hover > div. And this selector to exempt the child that is being hovered: .parent:hover > div:hover.
.test:hover ~ .test selects .test elements which are following siblings of a hovered .test element.
Instead, you can try :not(). The selector below will match all .test elements which are not hovered:
.test:not(:hover)
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.test:not(:hover) {
background-color: #ddd;
}
<div class="test">
Box 1
</div>
<div class="test">
Box 2
</div>
<div class="test">
Box 3
</div>
If you only want to match the non-hovered elements when one is hovered, you can use
:hover > .test:not(:hover)
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
:hover > .test:not(:hover) {
background-color: #ddd;
}
<div class="test">
Box 1
</div>
<div class="test">
Box 2
</div>
<div class="test">
Box 3
</div>
Alternatively, if you want it to work on old browsers that don't support :not(), you can apply the style to all elements, and reset in in the hovered element.
.test {
/* Set styles for non-hovered */
}
.test:hover {
/* Set styles for hovered */
}
.test {
width: 100px;
background-color: #ddd;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
.test:hover {
background-color: #009AFD;
}
<div class="test">
Box 1
</div>
<div class="test">
Box 2
</div>
<div class="test">
Box 3
</div>
.test {
/* Set styles for non-hovered */
}
:hover > .test:hover {
/* Set styles for non-hovered when another is hovered */
}
.test:hover {
/* Set styles for hovered */
}
.test {
width: 100px;
background-color: #009AFD;
height: 100px;
display: inline-block;
margin-right: 5px;
text-align: center;
}
:hover > .test {
background-color: #ddd;
}
.test:hover {
background-color: #009AFD;
}
<div class="test">
Box 1
</div>
<div class="test">
Box 2
</div>
<div class="test">
Box 3
</div>
I'm having some trouble creating a (somewhat strange) layout and I can't find an example anywhere of exactly what I'm trying to do.
I would like to layout multiple blocks that look like this:
<div class="rel">
<div class="item">--- a</div>
<div class="item">- b</div>
<div class="item">c</div>
</div>
where all of the .item elements are on top of one another, but the .rel elements layout normally so they are all visible. It's important to note that all the .item elements within a .rel will be of exactly the same length, yet they may be of any length, so they might wrap onto a new line. Here is an image of what I'm trying to do:
I've created this CodePen.
SOLUTION
In case anyone else finds themselves needing this truly strange layout:
CodePen
I am not exactly sure what you are trying to achieve, but it seems that you want <div class="item"> to display inline. you can use float=left or display=inline-block instead of absolute positioning. your divs are on top of each other right now .
Something similar to this
<div class="container">
<div class="rel clearfix">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
</div>
</div>
and
.container {
width: 200px;
}
.rel {
width: 100%;
background: steelblue;
margin: 1em;
padding: 1em;
position: relative;
}
.item {
color: white;
background: gray;
margin: .1em;
float:left;
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.clearfix { display: inline-block; }
.rel-2 {
width: 100%;
background: steelblue;
margin: .2em;
position: relative;
}
check it out here http://codepen.io/anon/pen/vEExvM
Use this on item
display: table-cell;
and this on rel
display: inline-block;
Have a look at this fiddle. http://jsfiddle.net/h8rzw65p/
Total Code:
.container {
width: 200px;
}
.item {
color: white;
background: gray;
margin: .1em;
top: 0px;
left: 0px;
display: table-cell;
}
.rel-2 {
top: 0px;
left: 0px;
width: 100%;
background: steelblue;
margin: .2em;
display: inline-block;
}
Or instead of table-cell you could do this on item:
float: left;