55

On my website, I'm constantly doing style="font-size: #ofpx;". However, I was wondering if there's a way to do it with scss so that, when I declare a class, it would also change the font size. For example:

<div class='col-lg-4 font-20'>whatever here</div>

and this would change my font-size to 20. If I did font-30, it would change my font-size to 30 and etc...

What I have so far:

.font-#{$fontsize} {
      font-size: $fontsize;
}
4
  • 15
    First: You're abusing CSS classes. Your classes shouldn't be named after the styles they impart, they should add semantic meaning to the elements. Second: Do you really have so many font sizes that you need this level of granularity? Commented Sep 15, 2016 at 19:04
  • There are a lot of different elements I wanna choose specifically the font-size ): Commented Sep 15, 2016 at 19:05
  • 2
    20 what? 30 what? Commented Sep 15, 2016 at 19:32
  • @connexo root em's, with a base font size of 24px. Commented Sep 14, 2018 at 0:51

6 Answers 6

73

This can't be done for arbitrary sizes. The nature of SCSS is that is needs to be flattened down to CSS before it gets applied to the HTML. What you are asking for, however, is essentially to create rules at run-time rather than compile-time.

In other words, SCSS makes it easier to write some of the repetitive parts of CSS, but it doesn't allow you to do anything new that wasn't already possible with plain old CSS.

What you're asking for is also a code smell. It smells like your markup isn't semantic enough. The purpose of a CSS class is to group objects with similar characteristics, but you're using them instead to describe the styles they impart. I would suggest stepping back and reconsidering what it is that you really want.

You obviously have details of certain elements that are context-dependent. For example, maybe you are applying these rules to buttons when you want to make them smaller or larger than usual. You need to identify the scenarios in which the buttons change. Maybe they are 20% smaller if they are in a modal dialog? Then write your normal .button rules, and also create rules for .modal .button which make it smaller.

If you're positive that you want to define font-size for each element within the HTML (and sometimes there are good reasons for doing so), just continue using inline styles. The only reason inline styling is frowned upon is because it combines model and view logic in a way that harms reusability; however, what you are requesting does so in exactly the same way. This is what inline styles were made for. Don't re-invent the wheel.

With all of that said, you can use sass loops to automatically generate classes for integers within a range. For example:

/* warning: this is generally a bad idea */
@for $i from 1 through 100 {
  .font-#{$i} {
    font-size: #{$i}px;
  }
}

This is not a good idea. Pragmatically speaking it doesn't offer any advantages over just using inline styles and with large ranges your resulting file will be larger (which affects website load times).


Aside: There is a CSS philosophy (or fad, if you're feeling ungenerous) called Atomic CSS (or sometimes Functional CSS) which defies the classical advice given in this answer. I won't give an opinion on its effectiveness at producing clean, maintainable code, but it does typically require more tooling than SCSS alone if used with the degree of specificity requested in this question.

Sign up to request clarification or add additional context in comments.

4 Comments

That was a really helpful answer. Thanks a lot and congrats for your knowledge :)
Why is this a terrible idea? Tailwindcss has implemented this exact idea, arbitrary values. Instead of using their set values you can set your own, ex “mt-[20px].” With that you can a top margin of 20px without messing with inline or the style sheet
@AnimeZone tailwind has a "compile" step that scans your templates for which classes you used and generates css from that. if you're using css (or scss) by itself, that step is missing. this is what i meant by "it does typically require more tooling than SCSS alone". if you're using something like tailwind, it comes with all the tooling you need.
This does have one difference over setting this value in a style tag. That difference being that style tags are much more specific than a class. If your project uses css modules, for example, and you allow developers to append a class name to the end of the list of classes for the root of that component for the purposes of overriding some style, then they could only ever override the style by using one or more !important statements. That, is a code smell. Generally when using css modules, you want everything to be a class. In this one narrow instance, this loop avoids specificity wars.
19

Just going to add, mixins are great, but if you want a util class (attach a class to an element, get that font-size applied to it, do a for-loop in SCSS like so..

@for $i from 1 through 4 {
    $fontsize: 10px * $i;
    .font-#{$i} { 
        font-size: $fontsize;
        }
}

compiles to

.font-1 {
  font-size: 10px;
}

.font-2 {
  font-size: 20px;
}

.font-3 {
  font-size: 30px;
}

.font-4 {
  font-size: 40px;
}

If you want the class to match the # of pixels...

@for $i from 1 through 4 {
    $base: 10;
    $fontsize: $base * $i;
    .font-#{$fontsize} { 
        font-size: $fontsize + 0px;
        }
}

Which compiles to

.font-10 {
  font-size: 10px;
}

.font-20 {
  font-size: 20px;
}

.font-30 {
  font-size: 30px;
}

.font-40 {
  font-size: 40px;
}

Codepen example.

Comments

5

When using "words" instead of "numbers" for variables, and the word not being at the end of the classname. I could work something out using CSS Attribute selectors ("wildcard selector"). I can iterate over a map object, and use text values to build CSS selectors.

SASS

//map
$colors: (
  primary: #121212,
  success: #8bcea8
);

//loop
@each $color, $value in $colors {
  //can't do this: div.first-class.is-style-#{$color}-component
  //can do this:
  div.first-class[class*="is-style-#{$color}-component"] {
     background-color: $value;
  }
}

HTML

<div class="first-class is-style-primary-component"></div>

This will generate a div.myComponent[class*="is-style-primary-component"] selector and so <div class="first-class is-style-primary-component"></div> (.first-class is not required, selector could be div[class*="is-style-#{$color}-component"] or even [class*="is-style-#{$color}-component"] only).

Yet, in some cases of CSS class naming, it could be limited due to the wildcard selector, which is "larger" than a specific class selector rule.

Comments

4

Of course, inline style tags are bad form. So yes, you should add some classes for font size, or just set font size on the elements you need to as you go. Up to you. If you want, you could use a mixin like so:

@mixin font-size($size) {
  font-size: $size;
}

.some-div { @include font-size(10px); }

But that's probably overkill unless you get a group of rules that usually go together.

3 Comments

Yeah what I really wanted is to declare the font-size in the class description suck as class="font-20"
You don't need sass for that. The comments you are getting on the main question are good ones. I will echo their sentiment that you are probably going about this the wrong way. Put semantics first in your thinking and you'll be happier in the long run.
are you even saving any typing with this?
3

Just for those of you who might stumble across this question in a more recent time and are new to FrontEnd Development.

What Woodrow Barlow said about using inline-styles instead of rule specific classes isn't quite an up-to-date opinion. For instance, Bootstrap has some of those and Tachyons is entirely built upon them. Actually this practice is called Atomic CSS or Functional CSS.

It's better explained by John Polacek in his CSS Tricks article: https://css-tricks.com/lets-define-exactly-atomic-css/

Comments

0

You can use mixins like this

    @mixin font($fontsize) {
      font-size: $fontsize;
    }

    .box { 
        @include font(10px); 
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.