FontAwesomeIcon (React) doesn't work with pseudoelements [duplicate] - css

Attempting to replace the bullet type on an list item tag with a Font Awesome icon but I am getting an empty square:
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems:before {
font-family: "Font Awesome 5 Free";
content: "\f058";
margin: 0 5px 0 -15px;
color: #004d00;
display: inline-block;
}
<script src="https://use.fontawesome.com/releases/v5.12.0/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
I know the font library is loading because I was able to use <i class="fas fa-check-circle"></i><li class="testitems">List Item 1</li> and the font rendered properly (though not styled properly).

If you are using the CSS version read this: Font Awesome 5, why css content is not showing?
Using the last release of the Font Awesome 5 you can enable the use of pseudo-element with the JS version by adding data-search-pseudo-elements like below:
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems:before {
font-family: "Font Awesome 5 Free";
content: "\f058";
display:none; /* We need to hide the pseudo element*/
}
/*target the svg for styling*/
.testitems svg {
color: blue;
margin: 0 5px 0 -15px;
}
<script data-search-pseudo-elements src="https://use.fontawesome.com/releases/v5.13.0/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
<i class="fa fa-user"></i>
You can check the documentation for more details :
If you’re using our SVG + JS framework to render icons, you need to do a few extra things:
Enable Pseudo Elements
Using CSS Pseudo elements to render icons is disabled by default when using our SVG + JS Framework. You’ll need to add the <script data-search-pseudo-elements ... > attribute to the <script /> element that calls Font Awesome.
Set Pseudo Elements’ display to none
Since our JS will find each icon reference (using your pseudo element styling) and insert an icon into your page’s DOM automatically, we’ll need to hide the real CSS-created pseudo element that’s rendered.

As stated in the docs of Font Awesome of how to enable Pseudo class...
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems::before {
font-family: "Font Awesome 5 Solid";
content: "\f058";
display: none;
}
.user::before{
font-family: "Font Awesome 5 Solid";
content: "\f007";
display: none;
}
<script>FontAwesomeConfig = { searchPseudoElements: true };</script>
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
<i class="fa fa-user"></i><br>
<a class="user" href="#">User</a>

If you install fontawesome in your project using a package manager (I'm using yarn on a Rails project), you have to import not only the js resource but also the css resource:
import "#fortawesome/fontawesome-free/js/all"
import "#fortawesome/fontawesome-free/css/all"

Related

Target the first child in a parent that doesn't have a specific class

The title is a mouthful but that's precisely what I'm trying to accomplish. I need to target the first instance where a class is not present - in this case I'm trying to hide the span in #3. This needs to be dynamic though as it won't always be #3. I tried getting sneaky with :not and :nth-of-type but its horribly wrong.
<style>
li:not(.done):nth-of-type(1).span.divider {display:none}
</style>
<-- 1 -->
<li class="wrapper done"><span class="divider"></span></li>
<-- 2 -->
<li class="wrapper done"><span class="divider"></span></li>
<-- 3 - hide this span -->
<li class="wrapper"><span class="divider"></span></li>
<-- 4 -->
<li class="wrapper"><span class="divider"></span></li>
<-- 5 -->
<li class="wrapper"><span class="divider"></span></li>
I think you will need to use two selectors for this:
/*hide all the element after .done selector without done*/
li.done ~ li:not(.done) {
display:none;
}
/*show all the element after the first one without .done*/
li.done ~ li:not(.done) ~ li {
display:list-item;
}
<ul>
<!-- 1 -->
<li class="wrapper done"><span class="divider">1</span></li>
<!-- 2 -->
<li class="wrapper done"><span class="divider">2</span></li>
<!-- 3 - hide this span -->
<li class="wrapper"><span class="divider">3</span></li>
<!-- 4 -->
<li class="wrapper"><span class="divider">4</span></li>
<!-- 5 -->
<li class="wrapper"><span class="divider">5</span></li>
</ul>
If it's always going to be after an element with the class .done then this should work: li.done + li:not(.done) .divider { display:none; }
My approach to the problem would be to use two separate rules; one to style all the elements lacking the given class-name and another to override all elements lacking the given class-name that follow an element lacking that class-name:
/* Selects all <li> elements with the 'wrapper'
class-name that does not have the 'done' class: */
li.wrapper:not(.done) {
color: limegreen;
}
/* Selects all elements, as above, that follow an
element without the 'done' class-name; effectively
we style the first occurrence using the above rule
because the first occurrence - obviously - cannot
be a general (later) sibling of a matching element: */
li.wrapper:not(.done)~li.wrapper:not(.done) {
color: red;
}
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
display: flex;
flex-wrap: wrap;
list-style-type: none;
width: 95vw;
margin: 0 auto;
}
li {
flex: 1 1 150px;
margin: 0.2em;
height: 10vh;
text-align: center;
line-height: 10vh;
border: 1px solid #000;
}
li.wrapper:not(.done) {
color: limegreen;
}
li.wrapper:not(.done)~li.wrapper:not(.done) {
color: red;
}
<ul>
<li class="wrapper done"><li>: 1</li>
<li class="wrapper done"><li>: 2</li>
<li class="wrapper done"><li>: 3</li>
<li class="wrapper"><li>: 4</li>
<li class="wrapper"><li>: 5</li>
<li class="wrapper"><li>: 6</li>
<li class="wrapper"><li>: 7</li>
<li class="wrapper"><li>: 8</li>
<li class="wrapper"><li>: 9</li>
<li class="wrapper"><li>: 10</li>
</ul>
References:
Negation (:not()) operator.
General sibling (~) combinator.

Font Awesome 5 SVG prevents pseudo chained icons from rendering [duplicate]

Attempting to replace the bullet type on an list item tag with a Font Awesome icon but I am getting an empty square:
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems:before {
font-family: "Font Awesome 5 Free";
content: "\f058";
margin: 0 5px 0 -15px;
color: #004d00;
display: inline-block;
}
<script src="https://use.fontawesome.com/releases/v5.12.0/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
I know the font library is loading because I was able to use <i class="fas fa-check-circle"></i><li class="testitems">List Item 1</li> and the font rendered properly (though not styled properly).
If you are using the CSS version read this: Font Awesome 5, why css content is not showing?
Using the last release of the Font Awesome 5 you can enable the use of pseudo-element with the JS version by adding data-search-pseudo-elements like below:
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems:before {
font-family: "Font Awesome 5 Free";
content: "\f058";
display:none; /* We need to hide the pseudo element*/
}
/*target the svg for styling*/
.testitems svg {
color: blue;
margin: 0 5px 0 -15px;
}
<script data-search-pseudo-elements src="https://use.fontawesome.com/releases/v5.13.0/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
<i class="fa fa-user"></i>
You can check the documentation for more details :
If you’re using our SVG + JS framework to render icons, you need to do a few extra things:
Enable Pseudo Elements
Using CSS Pseudo elements to render icons is disabled by default when using our SVG + JS Framework. You’ll need to add the <script data-search-pseudo-elements ... > attribute to the <script /> element that calls Font Awesome.
Set Pseudo Elements’ display to none
Since our JS will find each icon reference (using your pseudo element styling) and insert an icon into your page’s DOM automatically, we’ll need to hide the real CSS-created pseudo element that’s rendered.
As stated in the docs of Font Awesome of how to enable Pseudo class...
ul {
list-style: none;
}
.testitems {
line-height: 2em;
}
.testitems::before {
font-family: "Font Awesome 5 Solid";
content: "\f058";
display: none;
}
.user::before{
font-family: "Font Awesome 5 Solid";
content: "\f007";
display: none;
}
<script>FontAwesomeConfig = { searchPseudoElements: true };</script>
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<ul>
<li class="testitems">List Item 1</li>
<li class="testitems">List Item 2</li>
<li class="testitems">List Item 3</li>
<li class="testitems">List Item 4</li>
<li class="testitems">List Item 5</li>
</ul>
<i class="fa fa-user"></i><br>
<a class="user" href="#">User</a>
If you install fontawesome in your project using a package manager (I'm using yarn on a Rails project), you have to import not only the js resource but also the css resource:
import "#fortawesome/fontawesome-free/js/all"
import "#fortawesome/fontawesome-free/css/all"

Pseudo-class nesting / SCSS Linter Warning

I'm relatively new to SCSS and try to improve my skills using a linter. I have this little example, where I want to display a submenu only if the parent menu-item is hovered. While this code is working, the linter gives me a "Class should be nested within its parent Pseudo-class".
.menu-item {
.submenu {
display: none;
}
&:hover .submenu {
display: block;
}
}
<ul>
<li class='menu-item'>
<a href=''>
Menu 1
</a>
<ul class='submenu'>
<li>Submenu 1.1</li>
<li>Submenu 1.2</li>
</ul>
</li>
</ul>
I have no idea how the :hover part could be nested into the .submenu part. Can you help?
I found the solution and it was so simple, I just had to nest the .submenu into the hover part :(
.menu-item {
.submenu {
display: none;
}
&:hover {
.submenu {
display: block;
}
}
}
<ul>
<li class='menu-item'>
<a href=''>
Menu 1
</a>
<ul class='submenu'>
<li>Submenu 1.1</li>
<li>Submenu 1.2</li>
</ul>
</li>
</ul>
Your SASS code will compiled to the below CSS code which is working fine. Just make sure that your SASS code is properly compiling to CSS.
.menu-item .submenu {
display: none;
}
.menu-item:hover .submenu {
display: block;
}
<ul>
<li class='menu-item'>
<a href=''>
Menu 1
</a>
<ul class='submenu'>
<li>Submenu 1.1</li>
<li>Submenu 1.2</li>
</ul>
</li>
</ul>

Knockout.js & Bootstrap 3 - Bread Crumb Pseudo Element

I have run into an interesting bug. The CSS pseudo element does not disappear when it's associated element has display: none; in Bootstrap 3.0.2's breadcrumb component. jsFiddle To test: try switching the mode in the view model from "Mode 1" to "Mode 2".
I have a breadcrumb link that I am building using knockout.js. I switch the visibility of the pure li or li with nested a with knockout's visible: onSomeCondition binding. My understanding is that the non-visible li is set with display: none;. However, this does not remove the associated li in the DOM, and I think that makes the CSS keep the pseudo element. For example, I am expecting the following:
Mode 1 / Mode 2
But I get:
/ Mode 1 / Mode 2
The relevant knockout code is:
<ol class="breadcrumb">
<li data-bind="visible: isInMode1()">
Mode 1
</li>
<li class="active" data-bind="visible: !isInMode1()">Mode 1</li>
<li data-bind="visible: isInMode2()">
Mode 2
</li>
<li class="active" data-bind="visible: !isInMode2()">Mode 2</li>
</ol>
The relevant Bootstrap 3.0.2 CSS is below. Based on the Bootstrap style sheet, the "/" character is added as a pseudo "before" element.
.breadcrumb {
padding: 8px 15px;
margin-bottom: 20px;
list-style: none;
background-color: #f5f5f5;
border-radius: 4px;
}
.breadcrumb > li {
display: inline-block;
}
.breadcrumb > li + li:before {
padding: 0 5px;
color: #cccccc;
content: "/\00a0";
}
.breadcrumb > .active {
color: #999999;
}
If there is a better way to do this, or a cross-browser solution that I am not thinking of, I would be grateful for any input. I would prefer not to hack the CSS, but that may be the cleaner solution.
Thank you
Quick Links:
Bootstrap 3.0.2 Breadcrumbs
Knockout.js visible binding documentation
Don't use the "visible" binding, the separator will show even if the element is hidden. Use the "if" and "ifnot" bindngs:
<ol class="breadcrumb">
<li data-bind="if:isInMode1()">
Mode 1
</li>
<li class="active" data-bind="ifnot:isInMode1()">Mode 1</li>
<li data-bind="if:isInMode2()">
Mode 2
</li>
<li class="active" data-bind="ifnot:isInMode2()">Mode 2</li>
</ol>
For the sake of completeness, and because I very rarely find a question I can answer that doesn't already have a brilliant answer.....this is what to do:
<ol class="breadcrumb" data-bind="foreach: contentModel.breadcrumbs">
<!-- ko if: isInMode1($data) -->
<li data-bind="css: cssClass">
</li>
<!-- /ko -->
<!-- ko ifnot: isInMode1($data) -->
<li data-bind="css: cssClass, text: displayName"></li>
<!-- /ko -->
...repeat for isInMode2.......
</ol>
The if: and ifnot: bindings only render SUB elements depending upon their evaluation.....The element that contains the if/ifnot binding is always rendered.

Selector for one tag directly followed by another tag

This selects all <B> tags directly preceded by <A> tags:
A+B {
/* styling */
}
What is the selector for all <A> tags directly followed by <B> tags?
Here's sample HTML fitting my question:
<a>some text</a>
<b>some text</b>
Do you mean to style A given that it has a B element directly inside or followed? Like this:
<A>
<B>
</B>
</A>
// OR
<A>
</A>
<B>
</B>
You can't do such a thing in CSS (yet). Eric Meyer states that this kind of selector has been discussed quite a few times on the CSS mailing list, and isn’t doable. Dave Hyatt, one of the core WebKit developers, comments with a good explanation of why it can’t be done.
Check out: Shaun Inman's blog post and the comment by Eric Meyer.
David Hyatt weighs in, too.
You can’t in css.
Edit: To be a bit more helpful, if you use for example jQuery (a JavaScript library), you can use .prev().
You can ONLY do the converse: This selects all tags directly preceded by tags.
This is logically equivalent to your request.
I often use this to style a row of many checkboxes with labels
CSS:
label+input {
margin-left: 4px;
}
DOM:
<input id="a" name="a" type="checkbox"/><label for="a">...</label>
<input id="b" name="b" type="checkbox"/><label for="b">...</label>
<input id="c" name="c" type="checkbox"/><label for="c">...</label>
Although it's not very handy, nowadays you could achieve this behavior by reversing the order of your elements both when you generate the HTML and by applying the CSS rules: display: flex and flex-direction: column-reverse
ul {
display: flex;
flex-direction: column-reverse;
}
.b ~ .a {
color: red;
}
<ul>
<li class="a">A 3</li>
<li class="c">C 2</li>
<li class="c">C 1</li>
<li class="b">B 1</li>
<li class="a">A 2</li>
<li class="a">A 1</li>
</ul>
Also, if you have 2 or more inline elements, you could achieve it by applying float: right, as they will be displayed in reverse order:
ul {
float: left;
list-style-type: none;
}
li {
float: right;
}
li:not(:first-child) {
margin-right: 20px;
}
.b ~ .a {
color: red;
}
<ul>
<li class="a">A 3</li>
<li class="c">C 2</li>
<li class="c">C 1</li>
<li class="b">B 1</li>
<li class="a">A 2</li>
<li class="a">A 1</li>
</ul>
You can now use the :has() css selector (caniuse):
.first:has(+ .second) {
background: #ff0000;
}
That can be read: select all elements with class ".first" that are followed by element of class ".second"
<div class="first">Foo</div>
<div class="second">Bar</div>

Resources