-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow configuration for using px instead of rem #1232
Comments
You can configure Tailwind to use whatever units you want, just open up your https://tailwindcss.com/docs/theme We can only provide one default configuration and the default configuration we've chosen to provide uses |
I have an app where we are running bootstrap 3 which had the root font size set to 14px. The current rems are based off the assumption you use a 16px root font size. I know the config can be updated to change all of these values. However I love keeping the config as stock as possible so when tailwinds updates or adds other values or properties those new ones will just work. It would be great if there were a "defaultUnit" or "unit" or something setting in tailwind that defaults to "rem" but could be set to "px". I love tailwind because it can be so light weight and can be dropped into any project, but so much of it's config assumes that project already uses a root font size of 16px. I think it could be a lot easier to add to existing projects if there was an easy switch for pixels. For now Ill copy and past config and convert by hand ¯_(ツ)_/¯ |
I had this problem as well, so I did the conversion for font size, spacing and line height (assuming base 16px). I'll leave it here to save somebody some time. <3 tailwind
|
Thanks, @risingblock Just the thing I'm looking for :D |
@risingblock me too! |
@risingblock Thanks dude! |
I'm wondering if there is a way to grab the default configs, loop through it, and generate the px based config from that? It would save much time, especially when tailwind base is constantly updated. |
Have the same problem, when using shadow dom, the rem is controlled by outside html, the sdk use tailwindcss, so can not use rem, unless the consumer use 16px based rem too. |
@risingblock Thanks your sharing! I have a problem when I use "rem" of Tailwind. For example, "w-8" have to be "32px" equal "2rem" of Tailwind but when I go to my Chrome browser, it missing "2px" or "4px" and only have "30px", I have not configured anything yet 😥 |
FYI: if anyone wants to use the default config to convert to pixels, this VS Code plugin allows quick conversion: https://marketplace.visualstudio.com/items?itemName=sainoba.px-to-rem You can select all and convert at once. In my case I decided to go to the sections I needed and convert one-by-one to then copy over to my config file. This would be such a nice option to have baked in to know you don't have to manually specify these values (in case future properties are added). Wonder if a plugin can change such things or if that's outside the reach of plugins... |
Here's an update to @risingblock's config for Tailwind v3. It converts everything in the default config that uses rem to px (assuming 16px base). I used the px-to-rem extension suggested by @zbecknell's to do it quickly.
|
@joshua-scott I created a function that recursively looks after values that are formatted like float numbers and ending with "rem", and converts them to px.
You can then call it with the default theme by importing it:
And my theme configuration looks something like this:
|
Awesome @PooSham, although this really should be in the core config as "unit" or such... Don't you think? This feels kinda hackish.... |
Oh absolutely, but the tailwind devs don't seem too keen on implementing that, so I guess we'll have to live with hacks until they change their mind. |
@PooSham awesome! Using your function I simplified my tailwind config to this:
|
@PooSham I am a little confused about the first and second steps in your solution. Where do you store this function and where do you call it? |
@ineptian Sorry I wasn't clear, the second step doesn't call the function, it just imports the default configuration so that the function can be called with it later on in step 3. I have the function stored in tailwind.conf.js, before I export the configuration. The "require" line is in the beginning of the file. Here's a complete tailwind.conf.js: const defaultTheme = require("tailwindcss/defaultTheme");
function rem2px(input, fontSize = 16) {
if (input == null) {
return input;
}
switch (typeof input) {
case "object":
if (Array.isArray(input)) {
return input.map((val) => rem2px(val, fontSize));
} else {
const ret = {};
for (const key in input) {
ret[key] = rem2px(input[key]);
}
return ret;
}
case "string":
return input.replace(
/(\d*\.?\d+)rem$/,
(_, val) => parseFloat(val) * fontSize + "px"
);
default:
return input;
}
}
module.exports = {
content: ["src/**/*.{js,jsx,ts,tsx}"],
darkMode: "media",
theme: {
borderRadius: rem2px(defaultTheme.borderRadius),
columns: rem2px(defaultTheme.columns),
fontSize: rem2px(defaultTheme.fontSize),
lineHeight: rem2px(defaultTheme.lineHeight),
minHeight: {
...rem2px(defaultTheme.minHeight),
4: "16px",
8: "32px"
},
}
}; |
@PooSham Thanks. Got this working. This is slick. I do a lot of landing pages for random clients and sometimes their native REMS are whacky, so this helps a ton. In case anyone else that is illiterate like me needs clarification: Paste the following above
And then within the area where you define all your tailwind theme settings
I also agree that this should be native within tailwind. Would make using it even that much easier. Should be as simple as setting "rem" or "px" in the config I feel like. @joshua-scott How did you figure out how to implement this function with max-width like that? That is also super helpful, I took a shot at it myself before I saw that you had already figured it out. I am just wondering why it needs to be formatted differently than the others. Thanks to you both! |
Hi I know this is an old thread, but I think I figured out a better way to do this with postcss (assuming you are using postcss and want to apply the rem->px conversion across your project) Just install this postcss plugin and add it in your module.exports = {
plugins: {
tailwindcss: {},
'@thedutchcoder/postcss-rem-to-px': {}, // you can add option like the base font size
autoprefixer: {},
},
}; |
With big thanks to @PooSham function rem2px(input, fontSize = 16) {
if (input == null) {
return input;
}
switch (typeof input) {
case "object":
if (Array.isArray(input)) {
return input.map((val) => rem2px(val, fontSize));
} else {
const ret = {};
for (const key in input) {
ret[key] = rem2px(input[key]);
}
return ret;
}
case "string":
return input.replace(
/(\d*\.?\d+)rem$/,
(_, val) => `${input} /** ${parseFloat(val) * fontSize}px */`
);
default:
return input;
}
} |
I used this before I created the tailwind config function. It works ok, but it's another dependency on a project which is barely updated. I preferred to stay in control. |
That's not a bad idea, but this solution seems unnecessarily complex and actually incomplete. You should just update the "string" case, like this: function rem2px(input, fontSize = 16) {
if (input == null) {
return input;
}
switch (typeof input) {
case "object":
if (Array.isArray(input)) {
return input.map((val) => rem2px(val, fontSize));
} else {
const ret = {};
for (const key in input) {
ret[key] = rem2px(input[key]);
}
return ret;
}
case "string":
return input.replace(
/(\d*\.?\d+)rem$/,
(_, val) => `${input} /** ${parseFloat(val) * fontSize}px */`
);
default:
return input;
}
} |
@PooSham wow, something went terribly wrong with my debugging... somehow it got me confused with the fontSize object > array > object construction... think my docker cashed something there and messed up my conclusion. Thanks for the clarification, it works like a charm and you saved JetBrains a refund hahaha, i'll remove my code to not confuse anyone |
What if you want to use https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/ I think |
For anyone who is still looking for a workaround. I used postcss-rem-to-pixel to convert the output css from rem to px remToPixel.js
package.json
|
Thank @PooSham . And I do some other work on that:
const defaultTheme = require('tailwindcss/defaultTheme');
function rem2px(input, fontSize = 16) {
if (input == null) {
return input;
}
switch (typeof input) {
case 'object':
if (Array.isArray(input)) {
return input.map((val) => rem2px(val, fontSize));
}
const ret = {};
for (const key in input) {
ret[key] = rem2px(input[key], fontSize);
}
return ret;
case 'string':
return input.replace(
/(\d*\.?\d+)rem$/,
(_, val) => `${parseFloat(val) * fontSize}px`,
);
case 'function':
return eval(input.toString().replace(
/(\d*\.?\d+)rem/g,
(_, val) => `${parseFloat(val) * fontSize}px`,
));
default:
return input;
}
}
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['src/**/*.{js,jsx,ts,tsx}'],
theme: rem2px(defaultTheme),
}; |
This is a problem for me too. I ended up using a PostCSS plugin to convert rem-to-px automatically. I don't want to copy-paste things into tw config nor have to make choices on specific elements. The plugin I can toggle on/off. Use case: a Chrome Extension that injects a small floating UI (box with controls) onto every webpage visited, and I use TW to style it. Webpages in the wild all have crazy base styles that affect the box's UI. If I do nothing, then on one page the box will appear normal, and another webpage it'll be micro sized because someone thought setting |
I'm using twind.style to inject tailwind to shadow dom and managed to convert rem to px https://gourav.io/blog/tailwind-in-shadow-dom#configure-twind |
Thank guys. 🙏 I needed this because I'm implementing a widget library with Shadow DOM. Having the sizing in px is mandatory, because the widget will be added to any website |
This is exactly what I needed. Just in case anyone else is also confused, the plugin README has the incorrect name for the install instructions. You'll need
|
That's not really an answer good enough. it lacks in it's base any empathy to the use case mentioned |
Adding my +1 to re-open this! It would be nice to have a single option that would change all values rather than having to do it manually, add further dependencies or use a function inside I am developing an extension that injects a React app into the current tab of the user. To prevent any potential conflicts with existing styles, I have contained my app within a shadow root. However, given that rem values are inherently derived from the base html element, this causes inconsistencies in style rendering (ex: on one page Right now I'm fetching the text content of my stylesheet and using a regex to convert all // Fetch the CSS file
fetch(chrome.runtime.getURL('assets/styles.css'))
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok')
}
return response.text()
})
.then((text) => {
// Parse CSS text and convert rem values to px
const parsedText = text.replace(/(\d*\.?\d+)rem/g, (match, group) => {
// Convert rem to px based on base size 16px
const pxValue = parseFloat(group) * 16
return `${pxValue}px`
})
// Create a style element for the CSS file
const styleEl = document.createElement('style')
styleEl.textContent = parsedText
shadowRoot.appendChild(styleEl)
document.body.appendChild(root)
createRoot(shadowRoot).render(<ContentScript />)
})
.catch((error) => {
console.error('Failed to load CSS: ', error)
}) |
This is the most simple way to achieve quick rem to px convertion. |
The trouble is Tailwind's default config doesn't entirely use The net result is that most things will scale with the root font size, but some things won't. So this setup denies the user the ability to change their default text size independently from the scale of the entire design (e.g. to enlarge text for accessibility reasons), but it also fails to make the root font scale the site's design. Instead Tailwind designs effectively rely on the root font size at runtime being pretty close to a fixed value the designer had in mind, despite that value actually being dependent on the browser and the user's settings. The claimed advantage of using |
On desktop it might be good enough to scale everything together (but I don't think developers should do that - users can set a system-wide scaling if they prefer everything larger generally, or a site-specific one of course). However on mobile it can be a waste of screen space to also scale up spacing when the user just needs larger texts. I would prefer having not just one, but separate options for different kinds of sizes. |
I was in a situation where I needed to make Tailwind use em instead of rem (see #3105 (comment)). My solution should work for your case too with a modification: Here is a tiny PostCSS plugin, that replaces all occurrences of "rem" with "em" in the output CSS files:const convertRemToEm = {
postcssPlugin: 'convertRemToEm',
// When debugging this, https://astexplorer.net/#/2uBU1BLuJ1 is very helpful
Declaration(declaration) {
declaration.value = declaration.value.replaceAll(remRegex, 'em');
},
};
// Regex to find all occurrences of "rem" units
const remRegex = /(?<=\d)rem/g;
/** @type {import('postcss-load-config').Config} */
module.exports = {
plugins: [
// ... your other plugins here
// Add this plugin:
convertRemToEm,
],
}; If you want to use px instead, it might look something like this: const convertRemToEm = {
postcssPlugin: 'convertRemToEm',
// When debugging this, https://astexplorer.net/#/2uBU1BLuJ1 is very helpful
Declaration(declaration) {
declaration.value = declaration.value.replaceAll(
remRegex,
(_, number) => `${Number.parseInt(number) * 16}px`,
);
},
};
// Regex to find all occurrences of "rem" units and capture the number
const remRegex = /(\d+\.?\d+)rem/g;
/** @type {import('postcss-load-config').Config} */
module.exports = {
plugins: [
// ... your other plugins here
// Add this plugin:
convertRemToEm,
],
}; |
Hello! I'm facing the same issue, Im creating a web component and then I got into the same problem. Here's a sandbox in case you have some time, I cannot seem to bypass the html font sizing. This is a simpler example but if I get that going the rest should be fine |
Convert `rem` into `px` by this PostCSS plugin tailwindlabs/tailwindcss#1232 (comment)
Reporting in - @TheDutchCoder's postcss plugin is the way to go. |
Resize rem: function remResize(input, ratio = 1) {
if (input == null) {
return input;
}
switch (typeof input) {
case 'object':
if (Array.isArray(input)) {
return input.map((val) => remResize(val, ratio));
}
const ret = {};
for (const key in input) {
ret[key] = remResize(input[key], ratio);
}
return ret;
case 'string':
return input.replace(/(\d*\.?\d+)rem$/, (_, val) => `${parseFloat(val) / ratio}rem`);
case 'function':
return eval(input.toString().replace(/(\d*\.?\d+)rem/g, (_, val) => `${parseFloat(val) / ratio}rem`));
default:
return input;
}
} module.exports = {
theme: {
...remResize(defaultTheme, 0.625),
colors: {},
},
}; |
I don't really know why the previous issues #800 and #968 got closed without a real response.
There are as much valid use cases for using
rem
as there are for usingpx
.Lets take the simple example of a website builder which has two seperate user interfaces. One that includes all the App Components designed using Tailwind, and another which includes the user generated content. If I would like to scale up or down only the user generated content area of the UI by modifying the
font-size: 16px
property on the body element, it only works if the rest of the user interface has a fixed sizes usingpx
instead ofrem
. If everything usesrem
I can't change the size of things independently of each other.The text was updated successfully, but these errors were encountered: