The title says it all, I've just discovered that IE (9 - 11) automatically applies about 50% opacity to any element's border with border-style: dotted.
The weirdest thing is, it only happens on dotted in particular, solid and dashed are fine.
You can test it yourself: http://jsfiddle.net/ptv74f4q/1/
Any ideas?
This appears to be due to IE anti-aliasing the dotted border. If you make the border-width bigger than 1px (say 5px) the border will appear white again.
One way to get around this would be to overlay some pseudo elements with the same dotted border on top to counteract the opacity:
div {
width: 200px;
height: 200px;
background: #000;
}
span {
transform: rotate(0deg);
display: inline-block;
width: 180px;
height: 85px;
line-height: 85px;
text-align: center;
margin: 8px 8px 0 8px;
border: #fff 1px solid;
color: #fff;
position: relative;
}
span.dotted {
border-style: dotted;
}
span.dotted::before, span.dotted::after {
border: #fff 1px dotted;
content: "";
height: 100%;
left: -1px;
position: absolute;
top: -1px;
width: 100%;
}
<div>
<span>I'm with normal border</span>
<span class="dotted">I'm with dotted border</span>
</div>
JS Fiddle: http://jsfiddle.net/oyrbLyjc/1/
Alternative method
Alternatively you could try using border-image. There are online tools (e.g. https://developer.mozilla.org/en-US/docs/Web/CSS/Tools/Border-image_generator) that would be able to help you generate a similar border using this method.
I'm trying to mockup this design:
But, I can't render the red border correctly. I tried with the obvious solution:
border: 1px solid #939393;
border-left: 4px solid red;
But It's affected by the top and bottom borders, leaving the red stripe with diagonal corners, as you can see in this fiddle:
http://jsfiddle.net/anp0e03k/
Is there any way correct way to fix this?
The only thing that I can think is to add a div inside with red background and negative margins on top and bottom, but it seems to be an overkill and would love to find something that doesn't ruins the html semantic.
Apply the left border to a :before pseudo element of the div and remove the divs left border.
Compatibility: All modern browsers and IE8 +
Give the :before
height: 100% to span the entire height of your div
margin-top: -1px to overlap the top border
padding-bottom: 2px to overlap the bottom border
Then use either
position: absolute on the :before with position: relative on the div like this example:
body {
background-color: #c2c2c2;
}
div {
margin: 50px;
background-color: #FFF;
border: 1px solid #939393;
height: 50px;
width: 200px;
border-left: none;
position: relative;
}
div:before {
content: '';
display: block;
border-left: 4px solid red;
height: 100%;
margin-top: -1px;
padding-bottom: 2px;
position: absolute;
top: 0;
left: 0;
}
<div>
</div>
or
display: inline-block for the :before like this example:
Note: You will probably want to use vertical-align: top / middle / bottom for the :before. This example uses the value top.
body {
background-color: #c2c2c2;
}
div {
margin: 50px;
background-color: #FFF;
border: 1px solid #939393;
height: 50px;
width: 200px;
border-left: none;
}
div:before {
content: '';
display: inline-block;
border-left: 4px solid red;
height: 100%;
margin-top: -1px;
padding-bottom: 2px;
vertical-align: top;
}
<div>
There is text in this
</div>
Final result
I have a horizontal nav that has triangle borders inserted :before and :after a list item to make it appear as though there is a white bordered point on the right side of the list item. It's rendering in FF and Chrome but not IE8, and I'm using the html5 doctype and have included the html5.js.
It appears as though the list item background-color is stacked on top of the arrow border so it can't be seen because if I turn the background-color off I can see the arrow. I thought it might be a z-index problem but that doesn't help either. I also notice in IE that all of the :after styles are crossed out, any ideas?
<html>
<head>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<style type="text/css">
ul.registration-nav {
float: left;
margin-bottom: 45px;
width: 100%;
}
ul.registration-nav li {
background-color: #afafaf;
color: #FFFFFF;
display: block;
float: left;
font-weight: 600;
padding: 10px 0;
position: relative;
text-align: center;
text-decoration: none;
width: 33%;
}
ul.registration-nav li.arrow:after {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 15px solid #afafaf;
position: absolute;
top: 50%;
margin-top: -20px;
left: 100%;
z-index: 2;
}
ul.registration-nav li.arrow:before {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 24px solid transparent;
border-bottom: 24px solid transparent;
border-left: 18px solid white;
position: absolute;
top: 50%;
margin-top: -24px;
margin-left: 1px;
left: 100%;
z-index: 1;
}
ul.registration-nav li.checkout {
background-color: #cecece;
}
ul.registration-nav li.active {
background-color: #067673;
}
ul.registration-nav li.active:after {
border-left: 15px solid #067673;
}
</style>
</head>
<body>
<ul class="nav inline registration-nav capitalize">
<li class="register arrow active">Register</li>
<li class="books arrow">Books</li>
<li class="checkout">Checkout</li>
</ul>
</body>
</html>
FYI - Chris Coyier has an article on the after pseudo-selectors here
Browser Support
Little issues:
Firefox 3.5- wouldn't allow absolute positioning of pseudo elements.
In Opera 9.2, whitespace is always displayed within this
pseudo-element as if it’s pre text.
IE 8 doesn't support z-index on them
So this very well could have been your problem.
Link:
http://jsbin.com/EFAlace/3/edit?html,css,output
HTML:
<a href='#' class='tooltip-parent'>Hover over me!
<span class='tooltip-container'>
<span class='tooltip'>
<a style='href='#'>Weird link</a><br>
One<br>
Two<br>
Three<br>
Four<br>
</span>
</span>
</a>
.tooltip-container added for absolute positioning, for 'reset' tooltip position.
CSS (LESS):
.tooltip-container {
position: absolute;
}
a:hover {
background-color: grey;
}
.tooltip-parent {
display: inline-block;
.tooltip {
width: 150px;
display: none;
position:relative;
border:1px solid blue;
&:before, &:after {
content: '';
top: -20px;
left: 20%;
position: absolute;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-bottom: 20px solid white;
margin-left: -20px;
}
&:before {
border-left: 23px solid transparent;
border-right: 23px solid transparent;
border-bottom: 23px solid;
margin-left: -23px;
border-bottom-color: inherit; /* Can't be included in the shorthand to work */
top: -23px;
}
}
&:hover .tooltip {
padding: 10px;
display: inline-block;
top: 20px;
}
}
ul {
list-style:none;
margin: 0; padding:0;
li {margin: 0; padding:0;}
}
:before and :after: things are for triangle at the top of the tooltip. Google on 'CSS triangle pseudo elements'
I have been experimenting with CSS-only tooltip, which pops out on hover over a parent element. You can see working example at jsBin. But I encountered the strange issue - when I add anchor inside tooltip - html markup blows out, just uncomment this code <!--<a style='href='#'>Weird link</a><br>--> in HTML pane and you will see what Im talking about. And then see at markup structure - browser just places HTML content of .tooltip outside of and element to which that tooltip is attached.
Thats pretty unclear behavior, any thoughts will be appreciated.
first i see a problem of anchor inside anchor, that's not allowed by html. try to rearrange your html tags in a better way.
secondly about the weird link, which is:
<a style='href='#'>Weird link</a>
why is it
style='href='#'
I would like to add some style on a select box with the pseudo :after (to style my select box with 2 parts and without images). Here's the HTML:
<select name="">
<option value="">Test</option>
</select>
And it doesn't work. I don't know why and I didn't find the answer in the W3C specs. Here's the CSS:
select {
-webkit-appearance: none;
background: black;
border: none;
border-radius: 0;
color: white;
}
select:after {
content: " ";
display: inline-block;
width: 24px; height: 24px;
background: blue;
}
So is it normal or is there a trick?
I haven't checked this extensively, but I'm under the impression that this isn't (yet?) possible, due to the way in which select elements are generated by the OS on which the browser runs, rather than the browser itself.
I was looking for the same thing since the background of my select is the same as the arrow color. As previously mentioned, it is impossible yet to add anything using :before or :after on a select element. My solution was to create a wrapper element on which I added the following :before code.
.select-wrapper {
position: relative;
}
.select-wrapper:before {
content: '\f0d7';
font-family: FontAwesome;
color: #fff;
display: inline-block;
position: absolute;
right: 20px;
top: 15px;
pointer-events: none;
}
And this my select
select {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
width: 100%;
padding: 10px 20px;
background: #000;
color: #fff;
border: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
select::-ms-expand {
display: none;
}
I have used FontAwesome.io for my new arrow, but you can use whatever else you want. Obviously this is not a perfect solution, but depending on your needs it might be enough.
To my experience it simply does not work, unless you are willing to wrap your <select> in some wrapper. But what you can do instead is to use background image SVG. E.g.
.archive .options select.opt {
-moz-appearance: none;
-webkit-appearance: none;
padding-right: 1.25EM;
appearance: none;
position: relative;
background-color: transparent;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' height='10px' width='15px'%3E%3Ctext x='0' y='10' fill='gray'%3E%E2%96%BE%3C/text%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 1.5EM 1EM;
background-position: right center;
background-clip: border-box;
-moz-background-clip: border-box;
-webkit-background-clip: border-box;
}
.archive .options select.opt::-ms-expand {
display: none;
}
Just be careful with proper URL-encoding because of IE. You must use charset=utf8 (not just utf8), don't use double-quotes (") to delimit SVG attribute values, use apostrophes (') instead to simplify your life. URL-encode s (%3E). In case you havee to print any non-ASCII characters you have to obtain their UTF-8 representation (e.g. BabelMap can help you with that) and then provide that representation in URL-encoded form - e.g. for ▾ (U+25BE BLACK DOWN-POINTING SMALL TRIANGLE) UTF-8 representation is \xE2\x96\xBE which is %E2%96%BE when URL-encoded.
What if modifying the markup isn't an option?
Here's a solution that has no requirements for a wrapper: it uses an SVG in a background-image.
You may need to use an HTML entity decoder to understand how to change the fill colour.
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-repeat: no-repeat;
background-position: right .7em top 50%;
background-size: .65em auto;
Pinched from CSS-Tricks.
Faced the same problem. Probably it could be a solution:
<select id="select-1">
<option>One</option>
<option>Two</option>
<option>Three</option>
</select>
<label for="select-1"></label>
#select-1 {
...
}
#select-1 + label:after {
...
}
This post may help http://bavotasan.com/2011/style-select-box-using-only-css/
He is using a outside div with a class for resolving this issue.
<div class="styled-select">
<select>
<option>Here is the first option</option>
<option>The second option</option>
</select>
</div>
This solution is similar to the one from sroy, but with css triangle instead of web font:
.select-wrapper {
position: relative;
width: 200px;
}
.select-wrapper:after {
content: "";
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 6px solid #666;
position: absolute;
right: 8px;
top: 8px;
pointer-events: none;
}
select {
background: #eee;
border: 0 !important;
border-radius: 0;
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
text-indent: 0.01px;
text-overflow: "";
font-size: inherit;
line-height: inherit;
width: 100%;
}
select::-ms-expand {
display: none;
}
<div class="select-wrapper">
<select>
<option value="1">option 1</option>
<option value="2">option 2</option>
<option value="3">option 3</option>
</select>
</div>
This is a modern solution I cooked up using font-awesome. Vendor extensions have been omitted for brevity.
HTML
<fieldset>
<label for="color">Select Color</label>
<div class="select-wrapper">
<select id="color">
<option>Red</option>
<option>Blue</option>
<option>Yellow</option>
</select>
<i class="fa fa-chevron-down"></i>
</div>
</fieldset>
SCSS
fieldset {
.select-wrapper {
position: relative;
select {
appearance: none;
position: relative;
z-index: 1;
background: transparent;
+ i {
position: absolute;
top: 40%;
right: 15px;
}
}
}
If your select element has a defined background color, then this won't work as this snippet essentially places the Chevron icon behind the select element (to allow clicking on top of the icon to still initiate the select action).
However, you can style the select-wrapper to the same size as the select element and style its background to achieve the same effect.
Check out my CodePen for a working demo that shows this bit of code on both a dark and light themed select box using a regular label and a "placeholder" label and other cleaned up styles such as borders and widths.
P.S. This is an answer I had posted to another, duplicate question earlier this year.
<div class="select">
<select name="you_are" id="dropdown" class="selection">
<option value="0" disabled selected>Select</option>
<option value="1">Student</option>
<option value="2">Full-time Job</option>
<option value="2">Part-time Job</option>
<option value="3">Job-Seeker</option>
<option value="4">Nothing Yet</option>
</select>
</div>
Insted of styling the select why dont you add a div out-side the select.
and style then in CSS
.select{
width: 100%;
height: 45px;
position: relative;
}
.select::after{
content: '\f0d7';
position: absolute;
top: 0px;
right: 10px;
font-family: 'Font Awesome 5 Free';
font-weight: 900;
color: #0b660b;
font-size: 45px;
z-index: 2;
}
#dropdown{
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
height: 45px;
width: 100%;
outline: none;
border: none;
border-bottom: 2px solid #0b660b;
font-size: 20px;
background-color: #0b660b23;
box-sizing: border-box;
padding-left: 10px;
padding-right: 10px;
}
Instead of a wrapper element you can use CSS grid and place an icon (or whatever) in the same cell as the select:
.select-field {
display: grid;
grid-template:
"label"
"select"
/ max-content;
}
.label {
grid-area: label;
}
.select {
appearance: none;
background: white;
border: 1px solid var(--border-color);
grid-area: select;
padding-block: 0.5ex;
padding-inline: 1ch calc(1ch + 1em);
}
.after {
align-self: center;
border-block-start: 0.5em solid var(--border-color);
border-inline: 0.5em solid transparent;
block-size: 0;
grid-area: select;
inline-size: 0;
justify-self: end;
margin-inline-end: 1ch;
pointer-events: none;
}
.select,
.select + .after {
--border-color: silver;
}
.select:hover,
.select:hover + .after {
--border-color: grey;
}
.select:focus,
.select:focus + .after {
--border-color: rebeccapurple;
}
<div class="select-field">
<label for="my-select" class="label">Select One</label>
<select id="my-select" class="select">
<option value="foo">Foo</option>
<option value="bar">Bar</option>
<option value="baz">Baz</option>
</select>
<div class="after"></div>
</div>
Here I used an empty div to and styled it to be a CSS triangle which has the same color as the border which changes during hover/focus.
The most important bits here are the following:
The <select> and the <div class="after"> go into the same grid-area (which I named select). This will put the empty div over the select.
Give the <select> an appearance of none. This will remove any browser default style.
Give the <select> and extra padding at the end of the inline direction to make room for the empty style.
Justify the empty div to the end.
Give the empty div an extra margin at the end of the inline direction which matches your desired padding of the <select>
Give the empty div a pointer-events of none so the click will go through it to the <select> element.
Other then that you can do whatever with the empty div. It doesn’t even have to be empty. E.g. you can put an svg icon in there if you want.
If you chose to use the select::after method, remember that:
.select::after{
...
pointer-events: none;
...
for clickable..