Mixin for Group Pseudo Classes with SASS - css

Ideally I want to create a mixin to style all the placeholder pseudo classes. I'm not sure if this is even possible. Here's what I have:
#mixin placeholder($color) {
::-webkit-input-placeholder{
color: $color;
}
:-moz-placeholder {
color: $color;
}
::-moz-placeholder {
color: $color;
}
:-ms-input-placeholder {
color: $color;
}
}
Which ideally would be used like this:
input {
&#placeholder(red);
}
And would result in this CSS:
input::-webkit-input-placeholder{
color: red;
}
input:-moz-placeholder {
color: red;
}

Related

How can I pass a tag in as a scss mixin argument?

I am creating a mixin to target a child element.
Example.
Targeting all <a> tags of the parent that has a parent of section---blue
I figure that I can pass the tag as an argument as follows
But I am not getting the desired result
SCSS
#mixin themeParent ($child) {
&--blue $child {
color: getColour("theme", "bluehighlight");
}
&--green $child {
color: getColour("theme", "greenhighlight");
}
&--purple $child {
color: getColour("theme", "purplehighlight");
}
}
.section {
#include themeParent(a);
}
I would have thought that this would compile to
.section--blue a {
color: blue;
}
Can someone please explain to me why?
#mixin themeParent ($child) {
&--blue #{$child} {
color: blue;
}
}
outputs: .section--blue a { color: blue; }
If you want more specificity, just add another &:
#mixin themeParent ($child) {
&#{&}--blue #{$child} {
color: blue;
}
}
outputs: .section.section--blue a { color: blue; }
If you want more scability, just iterate over colors you want:
#mixin themeParent ($child) {
$colors: red, blue, green;
#each $color in $colors {
&#{&}--#{$color} #{$child} {
color: $color;
}
}
}
Put $child in #{$child}.
#mixin themeParent ($child) {
#{$child} {
color: #000;
}
}
.section {
#include themeParent(a)
}
Output:
.section a {
color: #000;
}
If I put this in a simple way, there is no need to pass the tag as a parameter to the mixin function instead, u should pass the color of the element.
<div className="section--blue">
<a>section blue</a>
</div>
<div className="section-green">
<a>section green</a>
</div>
mixin and css
#mixin themeParent ($color) {
color:$color;
}
.section{
&--blue {
a{
#include themeParent(blue);
}
}
--green{
a{
#include themeParent(green);
}
}
}
Hope this is useful.

Copy styles to other class in SCSS without #extend?

I'm trying to create a helper mixin in my SCSS file for easily styling form input placeholder texts. For a while, I only needed to change the text's color, so I had this mixin:
#mixin input-placeholder($color, $opacity, $focusColor: null, $focusOpacity: null) {
&:-moz-placeholder {
color: $color;
opacity: $opacity;
}
&::-moz-placeholder {
color: $color;
opacity: $opacity;
}
&:-ms-input-placeholder {
color: $color;
opacity: $opacity;
}
&::-webkit-input-placeholder {
color: $color;
opacity: $opacity;
}
&:placeholder {
color: $color;
opacity: $opacity;
}
&:invalid {
color: $color;
}
&:focus {
#if($focusColor==null) {
$focusColor: transparent;
}
#if($focusOpacity==null) {
$focusOpacity: 0;
}
&::-webkit-input-placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
&:-moz-placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
&::-moz-placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
&:-ms-input-placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
&::-webkit-input-placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
&:placeholder {
color: $focusColor !important;
opacity: $focusOpacity !important;
}
}
}
This purposely adds each selector separately and not in a comma separated list due to the fact that some browsers will ignore the entire entry if one is invalid.
I wanted to use #extend so that I could create a mixin like this:
#mixin style-input-placeholder($module) {
&:-moz-placeholder {
#extend #{$module};
}
&::-moz-placeholder {
#extend #{$module};
}
&:-ms-input-placeholder {
#extend #{$module};
}
&::-webkit-input-placeholder {
#extend #{$module};
}
&:placeholder {
#extend #{$module};
}
&:invalid {
#extend #{$module};
}
}
Where $module is the selector I pass to the mixin to extend the styles of, and I'd be able to use it like this:
.some-special-placeholder-styles {
color: purple;
opacity: 0;
text-transform: uppercase;
font-family: 'Open Sans', Arial, sans-serif;
}
input {
#include style-input-placeholder('.some-special-placeholder-styles');
}
It would allow me to modify more than just the color and opacity without having to annoyingly specify each attribute as a mixin parameter. But because of the nature of #extend, it combines all of those selectors into one comma separated list. So is there something else I can do or any workarounds that you've come across?
You can use #content directive to pass arbitrary content inside mixins (was added into sass 3.2). So your code may look like:
#mixin style-input-placeholder() {
&:-moz-placeholder {
#content;
}
&::-moz-placeholder {
#content;
}
&:-ms-input-placeholder {
#content;
}
&::-webkit-input-placeholder {
#content;
}
&:placeholder {
#content;
}
&:invalid {
#content;
}
}
input {
#include style-input-placeholder() {
color: purple;
opacity: 0;
text-transform: uppercase;
font-family: 'Open Sans', Arial, sans-serif;
}
}
Also you can try to wire your sass compilation with PostCSS and use excellent Autoprefixer plugin that will free you from defining all these vendor-specific prefixes.

How to extend in scss from parent (in case of BEVM)

I try to understand BEVM+SCSS philosophy.
I don't know how to extend V from BE in this case.
What I want to achieve:
.block {
&__element {
background-color: black;
&--variation-a {
#extend &__element; //won't work
color: red;
}
&--variation-b {
#extend &__element; //won't work
color: green;
}
}
}
What I want to avoid:
.block {
&__element {
background-color: black;
&--variation-a {
#extend .block__element; //work but ugly
color: red;
}
&--variation-b {
#extend .block__element; //work but ugly
color: green;
}
}
}
The only way I've found it's to have a kind of %element { ... } aside and extends from it, but it's not exactly what I want.
You can use variables. $b to store block name and $e to store element name.
Sassmeister demo.
.block {
$b: &;
&__element {
$e: #{$b}__element;
background-color: black;
&--variation-a {
#extend #{$e};
color: red;
}
&--variation-b {
#extend #{$e};
color: green;
}
}
}
But it's bad practice to nest element styles by modifier. Modifier must only override styles.

Compass (SASS) rule with pseudo class

Is it possible to generate css rule for element for normal state and some other pseudo state like this:
.heading-link, .heading-link:hover {
color: red;
}
with
.heading-link {
color: $state-info-text;
&:hover {
color: $state-info-text;
}
}
I got
.heading-link {
color: #538DA7;
}
.heading-link:hover {
color: #538DA7;
}
What is not as expected, plus I have to write rule for color twice.
You can use the parent selector (&) by itself, in addition to other selectors inside nested blocks.
DEMO
$state-info-text: #538DA7;
.heading-link {
&, &:hover {
color: $state-info-text;
}
}
Compiles to
.heading-link, .heading-link:hover {
color: #538DA7;
}
Yes. You can use Sass's built in #extend function for this.
$state-info-text: red;
.heading-link {
color: $state-info-text;
&:hover {
#extend .heading-link;
}
}
Gives the output:
.heading-link, .heading-link:hover {
color: red;
}

CSS LESS Placeholder Mixin

I want to create a placeholder mixin as follows. However, this fails to compile in LESS version 1.7.0.
.placeholder(...) {
::-webkit-input-placeholder: #arguments;
:-moz-placeholder: #arguments;
::-moz-placeholder: #arguments;
:-ms-input-placeholder: #arguments;
}
Mixin allows for any placeholder css rules.
.placeholder(#rules) {
&::-webkit-input-placeholder {
#rules();
}
&:-moz-placeholder {
#rules();
}
&::-moz-placeholder {
#rules();
}
&:-ms-input-placeholder {
#rules();
}
}
Example usage:
.placeholder({
color: #0000FF;
text-transform: uppercase;
});
Input placeholders are selectors, not properties, and so their CSS syntax is placeholder { ... }, not placeholder: ... which you are trying to generate.
If you fix that:
.placeholder(...) {
::-webkit-input-placeholder {border:#arguments}
::-moz-placeholder {border:#arguments}
:-ms-input-placeholder {border:#arguments}
}
It will compile, and when you call it:
.placeholder(solid; 1px; blue;);
it will generate this CSS:
::-webkit-input-placeholder {
border: solid 1px #0000ff;
}
::-moz-placeholder {
border: solid 1px #0000ff;
}
:-ms-input-placeholder {
border: solid 1px #0000ff;
}
(I just included border: as an example of a generic CSS property, independent of its actual effect on an input object)
You are missing the curly brackets around the placeholder selectors.
The styles should be as follows:
.placeholder(#color) {
::-webkit-input-placeholder {
color: #color;
}
:-moz-placeholder {
color: #color;
}
::-moz-placeholder {
color: #color;
}
}

Resources