Pseudo-class on pseudo-element - css

OK to be clear, I am not trying to make the (pseudo)inception for css. Just wanted to check if it's possible to add a pseudo class on a pseudo element. For eg:
.some-class:after:hover {
}
doesnt seem to work.
This works though:
.some-class:hover:after {
}
And ofcourse, this doesn't:
.some-class:hover:after:hover {
}
What I am trying to do is- there is a div. If you hover on that div, I am attaching a delete icon using :after on the div. I want to style this icon (say, have it zoom to 1.1 or so). Is this possible purely on CSS? I just need it to work on Chrome.

No, the current standard does not allow attaching pseudo-classes to pseudo-elements. The only place where a pseudo-element may appear is at the very end of a complex selector, and no other selectors or combinators may appear after it. Refer to the spec.
Some implementations like WebKit have their own rules, but they are non-standard and do not work cross-browser. They may also not apply to all pseudo-classes and/or all pseudo-elements. For example, as far as I know, :after:hover does not work on any browser, Chrome included.
Either way, you will need to use an actual element instead of a pseudo-element.

As already answered by #BoltClock that it is not possible to attach an :hover pseudo on :after so if you want, you can nest an extra element inside your container element and achieve the desired effect.
div {
height: 300px;
width: 300px;
border: 1px solid tomato;
margin: 20px;
position: relative;
}
div span {
display: none;
position: absolute;
right: 0;
top: 0;
}
div:hover span {
display: block;
transition: font-size .5s;
}
div span:hover {
font-size: 20px;
}
<div>
<span>X</span>
</div>
This will give you desired effect without using any JavaScript on your page, only down side of this is that you need to have an extra element so if you don't have any access or permission to modify your HTML then this is not for you unless you can then append an element using JavaScript.

Related

How to apply CSS to body tag in a child Div using SASS?

The scenario is I want to add CSS style for <body> on a child DIV
Whenever a DIV with a Fixed position is displayed, overflow will be hidden on the Body
.fixedDiv {
width: 100vw;
height: 50vh;
body {
overflow: hidden
}
}
Sass will always compile to css, so you always should ask yourself how to do it in css first.
What you are trying to achieve can be done using the :has pseudo selector.
body:has(.fixedDiv) {
overflow: hidden;
}
But at the time of writing, this selector is not yet fully supported by all major browsers. For Firefox it is still behind an experimental flag.
So I recommend to avoid using it for production projects yet. I am sure there is an alternative way of approaching the goal you are trying to achieve with a different layout.
it will be nice if you use the embedded css style attribute
or
the internal css way
.fixedDiv {
width: 100vw;
height: 50vh;
body {
overflow: hidden
}
}

Cannot get the :before element to appear on ReactiveForms input

I am trying to display a FormControl on a form to hold a telephone country code prefix, and I want it to always display a plus sign in the left-padding area. My bet was to use a :before element on the input, but surprisingly I cannot get it to appear in the DevTools inspector. When I started to notice the problem I even went despearate and tried to place the :before element on all inputs - to no avail. On the other hand, styles for the main input element work as expected.
Same goes with :after.
So my question is - does placing a :before or :after element work for anyone? Is it a know "feature" of ReactiveForms or a bug?
css
input[name="telCountryCode"]:before {
content: '+';
display: inline-block;
position: absolute;
top: 0;
left: 0;
width: 1rem;
height: 1rem;
}
ts
this.form = this.fb.group({
telCountryCode: '',
telNumber: '',
});
pseduo elements like :before/:after do not work on INPUT tag
wrap the input with div
<div class="telCountryCode-wrapper">
<input type="text" name="telCountryCode">
</div>
and use this css
.telCountryCode-wrapper{
position:relative;
}
.telCountryCode-wrapper:before{
content: '+';
display: inline-block;
position: absolute;
top: 0;
left: 0;
width: 1rem;
height: 1rem;
}
:before/:after renders inside a container only
You can't use :before/:after or other pseudo-elements for input.
Also img br hr etc.
It doesn't apply for self-closing elements.
Pseudo-elements can only be defined (or better said are only supported) on container elements. Because the way they are rendered are within the container itself as a child element.
input can not contain other elements hence they're not supported.
Refer this Can I use the :after pseudo-element on an input field?

Is it somehow possible to style an iframes before/after pseudo-element?

As the title says, is there a way to style an iframes pseudo before/after? Without wrapping the iframe with another div, or else?`
I tried to style it like any other element, but no success:
iframe::before {
content: 'foo';
position: absolute;
top: 0;
left: 0;
}
iframe::after {
content: 'bar';
position: absolute;
top: 0;
right: 0;
}
http://fiddle.jshell.net/ppRqm/
Update
A known workaround is to add the before/after to an element in the source file:
http://fiddle.jshell.net/ppRqm/2/
But sometimes you've no access to the source-file.
I am not sure but I think it isn't possible. Or the logic behind an iframe makes it imposible to achieve.
As you know, pseudo-elements are added to its container, if you do that with an iframe, pseudo-elements would be added inside the iframe.
But, and here's the problem, the iframe content, the inline content, will just load if the browser doesn't support iframes.
This means that this:
<iframe>
<div>Your browser doesn't support iframes</div>
</iframe>
And adding pseudo-elements, will do the same thing; on modern browsers inline content wouldn't be displayed.
Direct Work-Around for Debugging Purposes
I have a debugging CSS tier that gives an outline to elements with invalid or obsolete code. While not exactly an answer someone may find it helpful as I was trying to find a way to visually ensure that any content embedded with an iframe had an allowfullscreen="true" attribute/value. This work-around uses a sibling selector and it works well-enough.
iframe:not([allowfullscreen]) + *::after
{
background-color: #f00;
border: #f00 solid 4px;
color: #fff;
content: 'Missing allowfullscreen attribute on iframe!' !important;
font-size: 24px;
padding: 4px;
}
Direct Styling using Third Element
If you're looking to position relative to the iframe my next recommendation would be to set the iframe's parent position to position: relative; and then set position: absolute; on a third element to match the iframe's rendering. Lastly you could finally apply the ::after on that third element.

CSS not selector with after content

Is it possible to use the :not() selector/pseudo thing with :after?
So for example if I have the following:
li:hover > ul
{
display: block;
}
li:after
{
content: " ";
width: 200px;
height: 200px;
background: #cccccc;
position: absolute;
top: -100px;
left: -100px;
}
What happens is that if a person HOVERS over the content that is created by the after it will also make the child menu display block. In other words hovering other the LI or the AFTER content is acknowledged as hovering the LI. How would I stop this, so it only does the display block when hovering the ACTUAL LI and NOT the content created using AFTER.
I thought about: li:hover:not(:after) > ul { display: none; } but hasn't worked...
Also tried: li:after:hover > ul but also didn't work.
Any ideas for this? It might seem trivial but it's causes some issues in my design so need to stop it doing it asap.
As you observe, :hover styles on an element will be triggered when hovering over its contents, including descendants and pseudo-elements. However, you can't prevent :hover styles on an element from applying to its :after pseudo-element, nor can you use :not() to select :after pseudo-elements (this is explicitly disallowed by the spec).
This is by design, so the only way around it is to not use :after, but use JavaScript to generate some other element that you can append to the li and cancel the :hover effect on.
Actualiy it is possible with the use of the attribute "pointer-events" and assign it to none in the pseudo-element :after or :before .
So it would be -> pointer-events: none; in the pseudo-element.

In CSS, what is a better way of forcing a line break after an element than making it a block element?

I have an H3 heading that I'd like to style as having a particular background color, but without having the element's background take up the full width of the parent element. Seeing as H3 is by default a block element, my style would need to change the element to an inline-block element, or just an inline inline element like so:
h3 {
background-color: #333;
color: white;
display: inline-block;
}
This will work fine, but only if it is immediately followed by a block element. I do not want to change the markup just to cater for this style, so I was wondering if there is a way to cause any adjacent element, irrespective of how it displays, to start on the next line?
Assume I can use CSS3.
try this:
h3:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
display:block;
width:auto;
This will make the width as small as possible (not filling the whole parent element) and make other elements appear below.
How often does it happen that the element after the <h3> is an inline element? (Usually after a header there should be like a <p>, <ul> or other block elements, although this totally depends on your html. Is it predictable? Is it an option to just turn every element that directly follows a <h3> into a block element?
h3 ~ * { display: block }
The only other way I know to have a block-element not take up all the space is floating it, but this leaves another problem.
I come across this all the time in my code, usually for div's that are inline-block'ed. The best way I've seen is to force a new line is to wrap your code in an additional div. Your original html gets the formatting you expected and the div wrapper forces a new line.
Assuming this is your h3 styling,
h3 {
display: inline-block;
}
Then just wrap it in a div.
<div>
<h3>My heading</h3>
</div>
I've had to do something similar with inline nav items that need breaking at certain points. Does this work?
h3:after {
content: "\A ";
line-height: 0;
white-space: pre;
display:inline-block;
}
I seem to remember IE7 having an issue with it.
If you don't need to center h3, this may help:
h3 {
background-color: #333;
color: white;
display: inline-block;
float: left;
clear: left;
}

Resources