Styling pseudo-elements when a link has wrapped? - css

I've created an 'underline' animation that uses an ::after pseudo-element underneath the link. Here is the code for the link and the pseudo-element:
Link
a {
position: relative;
}
::after
a:after {
content: '';
display: inline;
position: absolute;
height: 2px;
width: 0%;
background-color: #ce3f4f;
left: 0%;
bottom: 0px;
transition: all 0.2s ease;
}
a:hover::after {
width: 100%;
}
This all works fine when the link is on a single line, but if the link flows onto the next line then it only fills across the bottom of the first line, as seen here:
http://i.stack.imgur.com/7SX7o.jpg
If I inspect the element then it appears that the issue is not solvable, as the browser (in this case, Firefox) isn't selecting the entirety of the wrapped element:
http://i.stack.imgur.com/342GH.jpg
Is there a way of solving this purely with CSS, or is it a problem with the way the browser renders the objects? I have played around with a lot of white-space, display and position configurations but to no avail.
Here's an example of the behaviour:
https://jsfiddle.net/57Lmkyf4/

This cannot be done with CSS. (I've implemented it using JS for links that wrap over not more than 2 lines: https://jsfiddle.net/6zm8L9jq/1/ - you can resize the frame to see it at work)
In my Chrome (39.0.2171.95) the underline under a wrapping a doesn't work at all, while in FF it displays like in your screenshot above. Primarily this is because your a element is inline (default), and when it wraps, any pseudo/child elements that depend on its width get 0 width in Chrome and the element's width on the first row in FF. Inline elements don't have control on their own width/height properties (eg, you can't set a width:100px on them without changing them to block elements), and this also affects any absolutely positioned elements that depend on them for width/height.
If you call the window.getComputedStyle method on the pseudo element in FF and Chrome, like:
var a = document.querySelector('a');
a.onmouseover = function(){
setTimeout(function(){
var width = window.getComputedStyle(a,':after').getPropertyValue('width');
console.log(width);
},300); //timeout so that animation to 100% width is completed
}
...in chrome you will see 0px while in FF you will see 100% - and neither will span to actual 100% of the parent. If you added a child element (eg a span) to a instead of a pseudo element, you could investigate the child's actual width after mouseover by calling getBoundingClientRect().width on the child, in which case again, in chrome you would see 0px, and in FF the width of the part of the parent element falling on the first line.
You can change the a element to display: inline-block and it will work, but it will obviously no longer wrap.

Related

How do I apply two filters on a background image?

I'm building a website with a fixed background image. It would be perfect for it to be both grayscale'd and blurred.
Since I discovered on my own that putting filter: blur(100%) would blur the whole page and its content, I learned that I could set my filters in a :before.
Here is my SCSS:
.front-layout {
font-family: 'Fira-Mono', 'monospace';
min-height: 100vh;
background: #0e0e0e fixed;
background-size: cover;
filter: grayscale(100%); <-- I somehow need it here
&:before {
content: "";
position: absolute;
width : 100%;
height: 100%;
background: inherit;
z-index: -1;
//filter: grayscale(100%) blur(5%); <-- What I want to achieve
filter: blur(5px);
}
// Some other elements
}
FYI, the background image is set dynamically directly in the HTML, that's why it doesn't appear here.
Somehow, I can't get rid of the filter outside the :before element, whatever it is, or the filter inside it won't work. To sum up, it's either both or neither of them.
How can I get rid of the first filter and apply two filters in my :before element?
Edit
I recreated a JSFiddle to make some more context, if you run my code, you won't see anything happening unless you uncomment what I commented.
Thank you in advance
The ::before pseudo element gets hidden behind the element itself (because of the negative z-index), and because that element has the same (un-manipulated) background, the pseudo element gets effectively hidden.
It would work this way, if you could set the background for the pseudo element only, and leave the element’s background transparent - but if you need to use background: inherit to get the pseudo element to inherit the parent’s background that was set via inline style, it can’t work this way.
Your only option then is to get your pseudo element positioned between the element’s own background, and its content - so effectively you need to elevate all content “one level up” - in the simplest way that could be done using
.front-layout > * {
position: relative;
z-index: 1;
}
https://jsfiddle.net/9sfqd7te/6/
Depending on what the element actually contains, and whether those descendants are themselves positioned in any way, it might work with only that; or you might have to make adjustments (like exclude certain elements from getting relative position applied if they are otherwise positioned already, and/or not overwrite a higher z-index they might already have.)
(.front-layout > * limits this to the children of the parent already, descendants further down the tree are no affected.)

Fixed position misbehaviour in IE11

I am experiencing elements position misbehaviour into my page, in IE(11) only; live link here. The logotext, the menu and the left sidebar text, remain in place doesn't move with the wrapper when the left slider is open (clicking on info+ button). I've read about position: fixed + transition in IE problems.
I've tried to apply position: expression(fixed); to the header but something went wrong and the wrapper receive a brake-movement at open/closing slider. (The sidebar didn't work with position: expression(fixed);)
Also I've tried to tweak the css modifying the element position values in static/ absolute but without succees.Tests are made in full screen, the theme is not for mobile screens.Any thoughts?
LE: I've found a possible solution that works with the slider in IE11:
.header {
position: absolute;
}
.bar-side {
position: absolute;
}
Will work with the slider but also will move on vertical scroll.If I ca fix that somehow, could be a solution.
This may be way too late, but I had a similar issue with position:fixed and IE11, for a full page DIV (by specifying top: 0; bottom: 0; left: 0; right: 0;). Worked fine on Chrome, Edge, Firefox and Opera, but IE11 displayed the DIV at way under the full viewport size, and with rounded corners that seem to have inherited somehow from the parent.
Playing with the IE11 developer tools, I found an alternate option suggested as a parameter for position - "-ms-page". Using position: -ms-page sorted the issue; preceding this with position: fixed allowed the other browsers to carry on regardless.
Hope this helps others with a similar problem...
For a quick solution add transform separately for IE, in IE only css hack.
#media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.header, #bar-left{
left: 0;
transition: all .5s;
}
.shiftnav-open .header, .shiftnav-open #bar-left{
left:590px;
}
}
Move the header outside the .shiftnav-wrap and place it above it, and apply the translateX seperately for header movement.
.shiftnav-open header{
transform: translateX(590px);
}
It is not good idea to depend on its movement relative to the outer div.
elements with fixed positioning are fixed relative to the viewport/browser window rather than the containing element - http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning
Another solution, you can use the header as absolute positioned, inside the left div #shiftnav-info.
ADD this script in your page. IE fixed position scroll issue fixed.
<script>
if(navigator.userAgent.match(/Trident\/7\./)) {
document.body.addEventListener("mousewheel", function() {
event.preventDefault();
var weelDelta = event.wheelDelta;
var currentOffset = window.pageYOffset;
window.scrollTo(0, currentOffset - weelDelta);
});
}
</script>

Child Hover not returning to unhovered state

I am trying to construct a chunk of code that is an image and a text caption, which is a single anchor. the image is an image tag and the text is in a DIV tag.
When the anchor is hovered, the image+text box has a border appear, and the text div transitions between text to then show the background image (using opacity 1 to 0)
USING CSS ONLY
My issue is that I can't seem to find the best CSS to write this code, what I have is:
HTML:
<div class="outerCCBox">
<a href="*url*" >
<img src="images/logo/clarityTeeth.png" alt="">
<div class="clarityUnderBox">
<div class="clarityBox">
Clarity Makeup
</div>
</div>
</a>
</div>
The "clarityUnderBox is a presized box containing the background image that appears when the covering text fades out on hovering over the anchor tag.
CSS:
.clarityUnderBox {
width:256px !important;
height:86px !important;
background:url('../../images/logo/Clarity-C-320.png') no-repeat;
background-size:contain;
}
.clarityBox {
width:100% !important;
height:100% !important;
background-color: #000;
opacity:1;
color:#f0f0f0;
transition: color 0.4s linear,opacity 0.6s;
}
All CSS is simplified for this question (fonts, transition -types- etc removed).
The issue I am having appears to be with the next piece of code, the "hover" element:
.outerCCBox a:hover > .clarityUnderBox .clarityBox {
opacity:0;
color:transparent;
}
EDITED CSS:
originally
.outerCCBox a:hover .clarityUnderBox .clarityBox {
opacity:0;
color:transparent;
}
which behaves in the same way, as with the ">" selector.
The issue is that the hover works fine when hovering over the anchor element but when moving away, the .clarityBox class doesn't return to it's pre-hover state.
1) How do I make this return to it's pre hover state?
1b) Do I need to make a separate ~ a:not-on-hover CSS declaration?
2) How can I tidy up and make the "hover" CSS line more specific? - the way I've done it above works, but I'm sure there's a better syntax to it. I have tried things like using "*" and ">" selectors with limited success (combined with some rearrangement of class orders in the HTML)
Thanks for your guidance.
EDIT:
As requested, a fuller fiddle is here:
http://jsfiddle.net/gwrrezys/9/
But this fiddle doesn't show the image above the text, but it does replicate the general issue with the hover not updating / or not returning to its original state.
cheers
SOLUTION:
As suggested in comments by Martin, making the anchor a block element fixed this issue, I have retained the issue in the jsFiddle for reference and can be found by repeatedly hovering and then hovering off the anchor area.
Your actual problem is with the hovered parent (your anchor element) not having a width set.
If you make the anchor a block element it will fix the "leaking" content issue. by either
making the anchor display: block with set width and height
or making the parent fit the content by making it display: inline-block
DEMO
General to displaying children on hovered parents:
As soon as you extend a child of a :hover element over the whole screen (100% width and height) the parent will stay in the hovered state as long as you are hovering over the child.
To get around that you need to break the child out of its parents flow ... for example by making it's position: fixed (or position: absolute if the parent has no position: relative).
For example by using something like this on the child - and the z-index: -1; here makes sure it moves behind the parent:
position: fixed;
width: 100%;
height: 100%;
top:0;
left: 0;
z-index: -1;
DEMO
Or (depending on what area exactly you wan to cover with the child) you can alternatively extend the child only over a particular hover area (e.g. its parent) ... here you would then use position:absolute on the child and position: relative on the parent (to make sure you keep the child in the parents flow).
DEMO
A quick read on positioning elements: http://css-tricks.com/absolute-relative-fixed-positioining-how-do-they-differ/

Setting opacity on image causes an overlapping element's box-shadow to go away

The following CSS, applied to an <a> and a <div> residing in individual <tr>▶<td> elements in a <table> (with border-collapse and td { padding: 0px; } set), works as expected:
a {
background-image: url("http://ibin.co/19rwR69EOigr");
height: 100px;
width: 120px;
display: block;
}
div {
width: 200px;
box-shadow: #000 0px 0px 13px;
}
If I apply any opacity to the <a>, the browser's internal layering seems to break horribly.
Note that the test picture's last pixel sits within the <div>'s box-shadow, even in the first example. (And it says opacity = ".99", if you can't see it in the image >.>)
Is this possibly a rendering bug that's managed to creep into both Firefox and Chrome? :P
See what opens and shuts in this JSFiddle.
Thanks in advance!
Quite Simple.
Thank you for clean formatting.
Change opaque ID to this:
#opaque {
opacity: .99;
z-index:-10;
position:relative;
}
http://jsfiddle.net/SinisterSystems/GbAYU/3/
What is happening is whenever opacity is set, the back-end method of CSS3 to interpret it throws some pretty wild z-index's.
Just set it to stack behind the other elements and all will work fine for you.
position:relative; - Cause otherwise it wouldn't accept your z-index property.
z-index:-10; - So that it places it behind the z-index of 0 of your other objects.
EDIT:
The default value of HTML elements does not support static as an object that z-index will apply to, hence the position declaration.
And it totally does with absolute, fixed, relative, or inherit, but not static.

IE7 Z-Index Layering Issues

I've isolated a little test case of IE7's z-index bug, but don't know how to fix it.
I have been playing with z-index all day long.
What is wrong with z-index in IE7?
Test CSS:
input {
border: 1px solid #000;
}
div {
border: 1px solid #00f;
}
ul {
border: 1px solid #f00;
background-color: #f00;
list-style-type: none;
margin: 0;
padding-left: 0;
z-index: 1000;
}
li {
color: #fff;
list-style-type: none;
padding-left: 0;
margin-left: 0;
}
span.envelope {
position: relative;
}
span.envelope ul {
position: absolute;
top: 20px;
left: 0;
width: 150px;
}
Test HTML:
<form>
<label>Input #1:</label>
<span id="envelope-1" class="envelope">
<input name="my-input-1" id="my-input-1" />
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
</span>
<br><br>
<label>Input #2:</label>
<span id="envelope-2" class="envelope">
<input name="my-input-2" id="my-input-2" />
</span>
</form>
Z-index is not an absolute measurement. It is possible for an element with z-index: 1000 to be behind an element with z-index: 1 - as long as the respective elements belong to different stacking contexts.
When you specify z-index, you're specifying it relative to other elements in the same stacking context, and although the CSS spec's paragraph on Z-index says a new stacking context is only created for positioned content with a z-index other than auto (meaning your entire document should be a single stacking context), you did construct a positioned span: unfortunately IE7 interprets positioned content without z-index this as a new stacking context.
In short, try adding this CSS:
#envelope-1 {position:relative; z-index:1;}
or redesign the document such that your spans don't have position:relative any longer:
<html>
<head>
<title>Z-Index IE7 Test</title>
<style type="text/css">
ul {
background-color: #f00;
z-index: 1000;
position: absolute;
width: 150px;
}
</style>
</head>
<body>
<div>
<label>Input #1:</label> <input><br>
<ul><li>item<li>item<li>item<li>item</ul>
</div>
<div>
<label>Input #2:</label> <input>
</div>
</body>
</html>
See http://www.brenelz.com/blog/2009/02/03/squish-the-internet-explorer-z-index-bug/ for a similar example of this bug. The reason giving a parent element (envelope-1 in your example) a higher z-index works is because then all children of envelope-1 (including the menu) will overlap all siblings of envelope-1 (specifically, envelope-2).
Although z-index lets you explicitly define how things overlap, even without z-index the layering order is well defined. Finally, IE6 has an additional bug that causes selectboxes and iframes to float on top of everything else.
http://www.vancelucas.com/blog/fixing-ie7-z-index-issues-with-jquery/
$(function() {
var zIndexNumber = 1000;
$('div').each(function() {
$(this).css('zIndex', zIndexNumber);
zIndexNumber -= 10;
});
});
In IE positioned elements generate a new stacking context, starting
with a z-index value of 0. Therefore z-index doesn’t work correctly.
Try give the parent element a higher z-index value (can be even higher than the child’s z-index value itself) to fix the bug.
I encountered this issue, but on a large project where HTML changes had to be requested and became a whole issue, so I was looking for a pure css solution.
By placing position:relative; z-index:-1 on my main body content my header drop down content suddenly displayed above the body content in ie7 (it was already displaying without issue in all other browsers and in ie8+)
The problem with that was then this disabled all hover and click actions on all content in the element with the z-index:-1 so i went to the parent element of the whole page and gave it a position:relative; z-index:1
Which fixed the issue and retained the correct layering functionality.
Feels a bit hacky, but worked as required.
I found that I had to place a special z-index designation on div in a ie7 specific styelsheet:
div { z-index:10; }
For the z-index of unrelated divs, such as a nav, to show above the slider. I could not simply add a z-index to the slider div itself.
If the previously mentioned higher z-indexing in parent nodes wont suit your needs, you can create alternative solution and target it to problematic browsers either by IE conditional comments or using the (more idealistic) feature detection provided by Modernizr.
Quick (and obviously working) test for Modernizr:
Modernizr.addTest('compliantzindex', function(){
var test = document.createElement('div'),
fake = false,
root = document.body || (function () {
fake = true;
return document.documentElement.appendChild(document.createElement('body'));
}());
root.appendChild(test);
test.style.position = 'relative';
var ret = (test.style.zIndex !== 0);
root.removeChild(test);
if (fake) {
document.documentElement.removeChild(root);
}
return ret;
});
It looks like not a ie bug, just for diffrent understanding to the css standard. If outside container is not specified the z-index, but the inner element specified a higher z-index. So the container's sibling maybe overlay the high z-index element. Even if like that, it only occurs in IE7, but IE6, IE8 and Firefox is ok.
In IE6 in general, certain UI-elements are implemented with native controls. These controls are rendered in a completely separate phase (window?) and always appear above any other controls, regardless of z-index. Select-boxes are another such problematic control.
The only way to work-around this issue is to construct content which IE renders as a seperate "window" - i.e. you can place a selectbox over a textbox, or, more usefully, an iframe.
In short, you'll need to put "on-hover" like things such as menu's in an iframe in order to let IE place these above built-in UI controls.
This should have been fixed in IE7 (see http://blogs.msdn.com/ie/archive/2006/01/17/514076.aspx) but perhaps you're running in some kind of compatibility mode?
This bug seems to be somewhat of a separate issue than the standard separate stacking context IE bug. I had a similar issue with multiple stacked inputs (essentially a table with an autocompleter in each row). The only solution I found was to give each cell a decreasing z-index value.
If you wanna create dropdown menu and having a problem with z-index, you can solve it by creating z-indexes of same value (z-index:999; for example).. Just put z-index in parent and child div's and that will solve problem. I solve the problem with that. If i put different z-indexes, sure, it will show my child div over my parent div, but, once i want to move my mouse from menu tab to the sub-menu div (dropdown list), it dissapear... then i put z-indexes of same value and solve the problem..
I solved it by using the developer tools for IE7 (its a toolbar) and adding a negative z-index to the container of the div that will be below that the other div.

Resources