Customizing the output of Compass sprites - sass

I have a top bar menu (that's based on Zurb's Foundation):
This is the SCSS:
.top-bar {
.top-bar-section {
ul {
#import "menu-icons/*.png";
#include all-menu-icons-sprites;
}
}
}
Now, this does what expected, but the problem is that I want to style the a element inside each li elements (actually, I'd like to apply it to .top-bar.topbar-section.ul.li.a:before).
However, since the site is build in WordPress, and so the menu, I can only assign the class to the li element and I have no idea how to make the Compass's spriting work.
I know, I could customize the way the menu is rendered by WordPress using a walker class, but I'd prefer to try finding a solution simply writing the right SCSS, providing that is possible.

There are a few sprite helper functions to be aware of when the default output isn't exactly what you want:
sprite-url
sprite-position
sprite-names (undocumented)
Using these you can apply the sprite styles to the children of the li elements:
.top-bar .top-bar-section ul > li {
// Generate the sprite map.
$menu-icons-sprite-map: sprite-map("menu-icons/*.png", $layout: smart);
// Set the background image.
> a:before {
background: sprite-url($menu-icons-sprite-map) 0 0 no-repeat;
}
// Set the background position for each sprite.
$menu-icons-sprite-names: sprite-names($menu-icons-sprite-map);
#each $name in $menu-icons-sprite-names {
&.menu-icons-#{$name} > a:before {
background-position: sprite-position($menu-icons-sprite-map, $name);
}
}
}

Related

SCSS fix for PrimeNG `pFocusTrap` bug when parent of focusable element is hidden

I found a bug in PrimeNG pFocusTrap.
Basically when tabbing through focusable elements, focus will get stuck on an element whose ancestor is display:none. Here is my fix:
$displays: inline inline-block block grid table table-cell table-row flex inline-flex;
$tabbable: 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
#function d-size($size) {
$ret: ();
#each $n in $displays {
$ret: append($ret,'.d-'+$size+'-'+$n,'comma');
}
#return $ret;
}
.d-none:not(#{d-size('sm')},#{d-size('md')},#{d-size('lg')},#{d-size('xl')}) *:is(#{$tabbable}),
.d-sm-none:not(#{d-size('md')},#{d-size('lg')},#{d-size('xl')}) *:is(#{$tabbable}),
.d-md-none:not(#{d-size('lg')},#{d-size('xl')}) *:is(#{$tabbable}),
.d-lg-none:not(#{d-size('xl')}) *:is(#{$tabbable}),
.d-xl-none *:is(#{$tabbable})
{
display: none !important;
}
Basically it applies display:none to any tabbable descendant of any elements that are using bootstraps d-xx-none utility.
My question is: I'm pretty new to SCSS, but is there any way to refactor and optimize the lines of code, and are there any bugs I may have overlooked?

Is there a way to combine scss nesting and tailwindcss?

I'm new to tailwindcss, and i want to use both sassy css and tailwind for my new project. But I'm having trouble with the nesting specially when i used "#apply".
section {
#apply .p-4;
ul {
li {
#apply .ml-8 .text-red-600;
li:last-child {
#apply .text-gray-300;
}
}
}
}
the red color apply to all li but the last-child (gray color) is not working. I'm not sure if it's possible
Right now we cant combine the SCSS and tailwind file. But we can achieve this by doing like this, give a class name to ul tag mylist
section {
#apply .p-4;
}
.mylist li {
#apply .ml-8 .text-red-600;
}
.mylist li:last-child {
#apply .text-gray-300;
}
You can use Sass and Tailwind together, though there are a few things to watch out for as detailed in the docs.
Though, as also noted in the docs it is recommended that you use PostCSS exclusively as your pre-processor. You can use nesting, variables and much, much more with PostCSS, there's really nothing that you can do with Sass that you cannot do with PostCSS.
I switched my build process from using Sass to PostCSS exclusively, more than 3 years ago, and I've not found anything missing. Indeed I can do so much more, I've never looked back.
Selector you're trying to build here will be compiled to something like:
section ul li li:last-child {...}
I think what you're trying to achieve here is this:
section {
#apply .p-4;
ul {
li {
#apply .ml-8 .text-red-600;
}
li:last-child {
#apply .text-gray-300;
}
}
}
Sure they can!
Nothing's wrong with them, there are couple of very small drawbacks but nothing special.
If your case, you have a tiny mistake in your code
section {
#apply p-4;
ul {
li {
#apply ml-8 text-red-600;
&:last-child {
#apply text-gray-300;
}
}
}
}

What is the best SASS practice of writing child selector while parent has hover

I have a doubt of writing child selector when I have a hover event in parent.
say I have HTML like this,
<div class="root">
<div class="root__element">
<div class="root__sub-element" />
</div>
</div>
In sass,
.root {
$root: &;
&__element {
&:hover {
#{$root}__sub-element {color: red;} // question comes here, why
// not using .root_sub-
// element?
}
}
}
what I want is hover event happens in root__element, color change in root__sub-element.
Should I use ampersand to keep SASS or I would directly use '.root__sub-element'?
You should Keep SASS.
I noticed you tagged 'bem' in your question.
As per BEM, your block element class to continue with your prefix of last child class. http://getbem.com/naming/
POINT 1:
If you have another element with the same behavior. the hardcoded class .root__sub-element will break. please consider the following sass code with multiple root classes.
SASS Code :
$roots: root, newroot;
#each $r in $roots {
.#{$r}{
$root: &;
&__element {
&:hover {
#{$root}__sub-element {color: red;}
}
}
}
}
POINT 2:
This is very rare or not suggested practice, but suppose in case your root block class .root changed to .newroot. as per bem, your child classes will change with new prefix.
Here, hardcoded class .root__sub-element will break, you need to changes it to all area manually.
Otherwise:
CSS is:
.newroot__element:hover .root__sub-element {
color: red;
}
Expected CSS:
.newroot__element:hover .newroot__sub-element {
color: red;
}

CKEditor config.stylesSet

I'm trying to get the dropdown styles option in CKEditor V4 configured. My test, shown below, does not work as expected. The dropdown style menu its self does display the "Green Check" option (label and the image used in the style) but its not applied to content of editor instance when used. I'm using the new inline editing feature (way cool it is too).
config.stylesSet = [
{ name: 'Green Check', element : 'ul li',
styles :
{
'background' : 'url(/images/bullets/greencheck.png) no-repeat top left;',
'list-style-type' : 'none;'
}
}
];
I specified the element element : 'ul li', because 'ul' obviously targets the ul element but when 'li' is specified, I get nothing in the dropdown menu or applied to content.
Here's more or less the complete style that I'm trying to configure...
ul.greencheck li{
list-style-type:none;
line-height:18px;
background: url(/images/bullets/greencheck.png) no-repeat center left;
padding-left:30px;
}
Any help gratefully received.
'ul li' isn't a valid element, you can use either 'ul' or 'li' but not both
You should remove also the ending semicolon in the styles 'none;' isn't valid, 'none' is the correct one
and instead of setting the inline styles it would be better to just apply a class to the UL and leave the styles to a separate css file.

CSS - Inheriting layered background images

CSS3 supports multiple background images, for example:
foo { background-image: url(/i/image1.jpg), url(/i/image2.jpg); }
I'd like to be able to add a secondary image to an element with a class though.
So for example, say you have a nav menu. And each item has a background image. When a nav item is selected you want to layer on another background image.
I do not see a way to 'add' a background image instead of redeclaring the whole background property. This is a pain because in order to do this with multi-backgrounds, you would have to write the base bg image over and over for each item if the items have unique images.
Ideally I'd be able to do something like this:
li { background: url(baseImage.jpg); }
li.selected { background: url(selectedIndicator.jpg); }
And have li.selected's end result appear the same if I did:
li.selected { background: url(baseImage.jpg), url(selectedIndicator.jpg); }
Update: I also tried the following with no luck (I believe backgrounds are not inherited..)
li { background: url(baseImage.jpg), none; }
li.selected { background: inherit, url(selectedIndicator.jpg); }
That is, in any case, not the way CSS inheritance works. inherit implies that an element should take on the attributes of it's parent element, not previous declarations affecting the same element.
What you want has been proposed as a way to make CSS more object-oriented, but the closest you will get is with a pre-processor like SASS.
For now you actually just have to re-state the first image along with the second.
I don't think this is possible, I think you'd have to redefine the whole rule every time.
For example, you could just add a "wrapper" around every item that has the initial background, with the actual item having a transparent background. Then add the background on the item itself when it's selected.
Additive CSS rules still aren't possible as far as I know.
You could try applying the second image to the ::after pseudo element:
li { background: url(baseImage.jpg); position: relative; }
li.selected::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: url(selectedIndicator.jpg);
}
I had the same need as you recently.
I finally thought about it and solved using css variables.
::root { --selectdropdown: url( '../elements/expand-dark.svg' ); }
select.gender.female { background-image: var(--selectdropdown), url( '../elements/female-dark.svg' ); }
When you resetting the attribute, just specify the variable again in the list!

Resources