Skip to content

Instantly share code, notes, and snippets.

@conradfuhrman
Last active October 31, 2023 14:36
Show Gist options
  • Save conradfuhrman/7c2cc87fef35804d594c87b005f1d92a to your computer and use it in GitHub Desktop.
Save conradfuhrman/7c2cc87fef35804d594c87b005f1d92a to your computer and use it in GitHub Desktop.
A simple clamp plugin for Tailwind
const plugin = require('tailwindcss/plugin')
// Usage For padding - default in px
// p-c-[20,40]
// p-c-[20px,40px]
// p-c-[20rem,40rem]
// p-c-[40px,200]
// Usage For Text
// text-c-[24px,96px]
// text-c-[24,96]
// text-c-[2rem,5rem]
// text-c-[24,36,1.5,1.2]
// text-c-[24px,36px,1.5,1.2]
// text-c-[2rem,4rem,2,1.5]
module.exports = plugin(function ({ matchUtilities }) {
const minViewport = 375;
const maxViewport = 3840;
const baseFontSize = 16;
function createClampValue(values) {
let v = values.split(',')
let pixelSizeAtMinViewport = toPixels(v[0])
let pixelSizeAtMaxViewport = toPixels(v[1])
// Calculate a and b
const a =
(pixelSizeAtMaxViewport - pixelSizeAtMinViewport) /
(maxViewport - minViewport);
const b = pixelSizeAtMinViewport - a * minViewport;
// Adjust a for the vw unit
const aVw = (100 * a).toFixed(4);
// Convert pixel values to rem (assuming 1rem = 16px)
const minRem = (pixelSizeAtMinViewport / baseFontSize).toFixed(4);
const maxRem = (pixelSizeAtMaxViewport / baseFontSize).toFixed(4);
const bRem = (b / baseFontSize).toFixed(4);
// Form the clamp value
const clampValue = `clamp(${minRem}rem, ${bRem}rem + ${aVw}vw, ${maxRem}rem)`;
return clampValue;
}
function createLineHeightClamp(values) {
let v = values.split(',')
v[2] = v[2] || 1.5;
v[3] = v[3] || 1.3;
let pixelSizeAtMinViewport = toPixels(v[0]) * v[2]
let pixelSizeAtMaxViewport = toPixels(v[1]) * v[3]
let lineHeight = pixelSizeAtMinViewport + ',' + pixelSizeAtMaxViewport
return createClampValue(lineHeight)
}
function toPixels(value) {
// If value is in rem, convert to px
if (value.endsWith('rem')) {
return parseFloat(value) * baseFontSize;
}
// If value is in px, just return the numeric value
if (value.endsWith('px')) {
return parseFloat(value);
}
// If value is a plain number, return it as a number
if (!isNaN(value)) {
return parseFloat(value);
}
// If the value doesn't match any known formats, return it as-is
return value;
}
matchUtilities({
"p-c": (value) => ({
padding: createClampValue(value),
}),
"pt-c": (value) => ({
paddingTop: createClampValue(value),
}),
"pr-c": (value) => ({
paddingRight: createClampValue(value),
}),
"pb-c": (value) => ({
paddingBottom: createClampValue(value),
}),
"pl-c": (value) => ({
paddingLeft: createClampValue(value),
}),
"px-c": (value) => ({
paddingLeft: createClampValue(value),
paddingRight: createClampValue(value),
}),
"py-c": (value) => ({
paddingTop: createClampValue(value),
paddingBottom: createClampValue(value),
}),
"m-c": (value) => ({
margin: createClampValue(value),
}),
"mt-c": (value) => ({
marginTop: createClampValue(value),
}),
"mr-c": (value) => ({
marginRight: createClampValue(value),
}),
"mb-c": (value) => ({
marginBottom: createClampValue(value),
}),
"ml-c": (value) => ({
marginLeft: createClampValue(value),
}),
"mx-c": (value) => ({
marginLeft: createClampValue(value),
marginRight: createClampValue(value),
}),
"my-c": (value) => ({
marginTop: createClampValue(value),
marginBottom: createClampValue(value),
}),
"text-c": (value) => ({
fontSize: createClampValue(value),
lineHeight: createLineHeightClamp(value),
}),
"tracking-c": (value) => ({
letterSpacing: createClampValue(value),
}),
"w-c": (value) => ({
width: createClampValue(value),
}),
"h-c": (value) => ({
height: createClampValue(value),
}),
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment