Using mathematical operations in Sass mixins with variable arguments

When working with CSS sizing, I prefer using rem units with pixel fallbacks and am currently creating mixins to streamline the process. For setting font sizes, it's a simple task:

@mixin font-size($size) {
  font-size: $size + px;
  font-size: ($size / 10) + rem;
}

However, when dealing with padding, margins, and similar properties, the mixin needs to accept variable arguments. The Sass documentation mentions that this is achievable here.

The issue arises when using the following mixin - instead of dividing by 10, the numbers are being combined with a slash. For example:

@mixin padding($padding...) {
    padding: $padding + px;
    padding: ($padding / 10) + rem;
}
.class {
    @include padding(24);
}

This results in:

.class {
    padding: 24px;
    padding: 24/10rem;
}

What I actually want is:

.class {
    padding: 24px;
    padding: 2.4rem;
}

Is there a way to ensure that Sass recognizes the variables as numbers so that the division operator works correctly?

Upon further testing, I noticed that the concatenation only occurs on the last variable.

Answer №1

Give this a shot:

padding: #{$padding / 10}rem;

In SASS/SCSS, concatenation follows Ruby syntax. Mixing a mathematical equation with concatenation may lead to issues because it involves variable type mixing.

When using expressions and variables within #{here}, they are evaluated separately from the rest of the line. This helps prevent unintentional quoting in your output (you can also use the unquote() function for this purpose).

Answer №2

After realizing that using a list instead of a variable argument was the key to manipulating each value separately, I attempted to achieve this using the @each directive within a declaration block. However, my initial approach led to an error:

@mixin padding($padding) {
   padding: @each $value in $padding { $value + px };
   padding: @each $value in $padding { ($value / 10) + rem };
}

Subsequently, I opted for a more verbose solution where I handled the four possible cases individually (1, 2, 3, or 4 arguments). This revised method achieved the desired outcome:

@mixin padding($padding) {
    @if length($padding) == 1 {
        padding: $padding+px;
        padding: $padding/10+rem;
    }
    @if length($padding) == 2 {
        padding: nth($padding, 1)+px nth($padding, 2)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem;
    }
    @if length($padding) == 3 {
        padding: nth($padding, 1)+px nth($padding, 2)+px nth($padding, 3)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem nth($padding, 3)*0.1+rem;
    }
    @if length($padding) == 4 {
        padding: nth($padding, 1)+px nth($padding, 2)+px nth($padding, 3)+px nth($padding, 4)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem nth($padding, 3)*0.1+rem nth($padding, 4)*0.1+rem;
    }
}

To make this and other rem mixins accessible, I have compiled them as a Gist here: https://gist.github.com/doughamlin/7103259

Answer №3

Utilizing calc in conjunction with interpolation (also known as #{}) can be beneficial. For instance.

$height: 10px;
$padding: 2px;

height: calc(#{$height} + #{$padding * 2}); // calc(10px + 4px)

This approach differs from...

height: calc($height + #{$padding * 2});
// results in...
height: calc($height + 4px); // ERROR

height: #{$height + $padding * 2};
// results in...
height: 10px + 4px; // ERROR

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Font Color in Gmail HTML Emails

While working on styling an HTML email, I've encountered an unexpected issue with inline CSS in Gmail. I set the color of text in a table row using the following code: <tr style='color: #000; font-size: 14px; font-family: Verdana, serif;' ...

Tips for achieving equal width li elements within various columns in Bootstrap 4 beta 2 and ensuring they span the full screen width

I've been scratching my head for a while, but I just can't seem to make it work. On the fiddle link provided, you'll notice three main blocks in light gray, each containing a variable number of smaller dark blocks. My goal is to have these s ...

Alert: Font preload was not utilized within a short timeframe after the window's load event

I've been working on optimizing the loading speed of fonts on my website, so I added the following: <link rel="preload" href="{{ '/css/fonts/bebasneue-webfont.woff' | prepend: site.baseurl | prepend: site.url }}" as="font" type="fo ...

Display or conceal a YouTube video with a click

Q1) Is it possible to use JQuery on page load to detect the file name of an image and then dynamically position it on the page with CSS? Q2) What is the most efficient way to achieve this without embedding iframe code inside a specific div.icon element? ...

Using a subheader in conjunction with a virtual repeater in markdown does not function correctly

Currently, I am utilizing angular 1 along with angular material. I am trying to incorporate md-subheader with multiple md-virtual-repeat-containers within an ng-repeat loop. The source code can be found on this codepen. The issue I am facing is slightly c ...

CSS cascading not happening

Within the usersettings.css.erb file, line numbers are provided for easier reference. 11 #userSettingMain .form-horizontal .controls { 12 13 margin-left: 30px; 14 } 15 16 #user_birthday_3i{ 17 18 margin-left: 0px; 19 } U ...

Update the appearance of an element in real-time using VUEJS

I am trying to use VueJS to dynamically change the position of a div. In the data function, I have a variable called x that I want to assign to the top property. However, the code I wrote doesn't seem to be working. Here is what it looks like: <tem ...

Displaying images in a carousel below a fixed navigation bar using Bootstrap

Check out my website at When viewing on smaller screens like mobile devices, I'm facing issues with my carousel images overlapping the navbar. Any suggestions on how to keep them below the navbar? Also, the third image appears shorter in length compa ...

The feature of Jquery click and cursor: pointer only focuses on a single element at a

Recently, I created a navbar that includes a dropdown feature. I encountered an issue where I wanted the dropdown to show up when clicking on the navbar-profile class (which contains the profile picture, name, and chevron icon) in the top right corner. Ho ...

photos arranged in rows rather than a single row

Looking for help with arranging the remaining photos in the second row? Check out this example image link. I'm struggling to organize a row of overflow images within the "small-img-row" division. This row is located under the main image in col-2. H ...

Enhance your inline content by adding adjacent inline blocks

My objective is to include a "Read More" link alongside a text block, which should appear next to the text without forming a new line or block. The challenge lies in the fact that the content of the text block is created using TinyMCE, resulting in various ...

Implementing CSS keyframe animations in a customized Material UI component using React, Material UI, and JSS

I'm facing an issue with adding a CSS keyframe animation to my Material UI custom styled component. Whenever I try to add a keyframe animation, it throws an error in my code setup: const PulsatingCircle = styled("div")(({ theme, }) => ( ...

Achieving Vertical Content Alignment in Bootstrap 4

I am struggling to achieve a responsive design where two columns stack vertically on top of each other when viewed on smaller mobile screens. Despite numerous attempts, I have been unable to figure it out. Ideally, I want the layout to look like this imag ...

The hover effect is not functioning properly after loading jQuery with load();

When loading elements into a div using the load() function, I noticed that the :hover effect in CSS stops working for those elements. It's a dynamic menu setup, as shown below: <div id='main-menu'> <ul> <li class='click ...

The alignment of the image in the Bootstrap dropdown menu is disrupted

Hello! Currently, I am utilizing this bootstrap template from . However, I am encountering an issue with the dropdown menu alignment when I try to add an image to it. Is there anyone who can provide some assistance with this problem? The complete code was ...

Ways to enable file/result downloads on a website using HTML

Could you please take a look at this repository: https://github.com/imsikka/ArtGallery I am looking to create a downloadable result using a download button. I can create the button, but I am unsure of how to make the file actually downloadable. Do I need ...

dynamic resizing, uniform dimensions

Is it possible to use CSS to ensure that an image is 100% the width of a fluid div without distorting the square shape? The goal is to match the height to the width for a cohesive look. Currently, I am using the following code for fluid width: .img{ max ...

Paragraph opacity adjustments can alter both the text and background opacities

Is there a way to change the opacity of only the background of a paragraph without affecting the text? When I try to adjust the opacity, it changes both the text and the background. How can I resolve this issue? HTML <div id="opener"> <p id="in ...

Experiencing an issue with the left side menu bar in Bootstrap, looking to incorporate additional sub menu items

<li class="drop-menu-tab"> <a class="dropmenu" ><i class="icon-folder-close-alt"></i><span> Employee</span></a> <ul> <li><a class="submenu&q ...

Error Encountered: TemplateSyntaxError on the User Profile Page

I encountered an error: TemplateSyntaxError at /accounts/profile/ <ExtendsNode: extends "registration/accounts/base.html"> must be the first tag in the template The content of base.html is as follows: {% load staticfiles %} <htm ...