dynamic value change

Open
#43,118 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
32/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Active
Tech stack
bootstrap, css, html, javascript
Domain
design, frontend

Research direction

Start with the proposed data-attribute and JavaScript behavior in the issue and review Bootstrap’s relevant utility and data-bs-* implementation entry points. Define the supported attributes, value syntax, defaults, precedence, runtime updates, and accessibility implications. Done means maintainers approve the API and it has agreed implementation, tests, and documentation; the issue currently provides none of these or a scoped codebase location.

Written by the indexing model from the issue text.

Description

feature js utility-api v6
Prerequisites
Proposal

I don't know is it good or bad. but this feature I think reduce some headache.

Bootstrap provides utility classes like h-100, w-100, and vh-100 for fixed sizing, but there's no built-in way to express dynamic offsets without writing custom CSS or inline styles. A common need is:

style="height: calc(100% - 60px)"

I propose a set of data-* attributes that let developers apply dynamic values directly in HTML, similar in spirit to the existing data-bs-* attributes.

How it works:

Instead of h-100, a developer could write data-h="-60px", which resolves to calc(100% - 60px). The default unit is inferred from the base class:

data-h → calc(100% <op> <value>)

data-vh → calc(100vh <op> <value>)

data-w → calc(100% <op> <value>)

data-vw → calc(100vw <op> <value>)

If no unit is provided, the default unit for that property is applied (e.g., px for margins/padding/font-size). If a unit is provided (e.g., 1.5rem), it is respected.

Additional attributes for spacing and typography:

Margins: data-m, data-mt, data-me, data-ms, data-mb, data-mx, data-my

Padding: data-p, data-pt, data-pe, data-ps, data-pb, data-px, data-py

Font size: data-fs

Example:

I am 50px from the top, centered horizontally, have 1.5rem bottom padding, and an 18px font size.

Reference implementation (JavaScript):

function applyDynamicStyles() {
  const elements = document.querySelectorAll(
    "[data-h], [data-vh], [data-w], [data-vw], [data-m], [data-mt], [data-me], [data-ms], [data-mb], [data-mx], [data-my], [data-p], [data-pt], [data-pe], [data-ps], [data-pb], [data-px], [data-py], [data-fs]"
  );

  elements.forEach((el) => {
    if (el.dataset.h) {
      const offset = parseOffset(el.dataset.h, "px");
      el.style.setProperty("height", `calc(100% ${offset.op} ${offset.val})`, "important");
    }
    if (el.dataset.vh) {
      const offset = parseOffset(el.dataset.vh, "vh");
      el.style.setProperty("height", `calc(100vh ${offset.op} ${offset.val})`, "important");
    }
    if (el.dataset.w) {
      const offset = parseOffset(el.dataset.w, "px");
      el.style.setProperty("width", `calc(100% ${offset.op} ${offset.val})`, "important");
    }
    if (el.dataset.vw) {
      const offset = parseOffset(el.dataset.vw, "vw");
      el.style.setProperty("width", `calc(100vw ${offset.op} ${offset.val})`, "important");
    }

    if (el.dataset.m) el.style.setProperty("margin", applyUnit(el.dataset.m), "important");
    if (el.dataset.mt) el.style.setProperty("margin-top", applyUnit(el.dataset.mt), "important");
    if (el.dataset.me) el.style.setProperty("margin-right", applyUnit(el.dataset.me), "important");
    if (el.dataset.ms) el.style.setProperty("margin-left", applyUnit(el.dataset.ms), "important");
    if (el.dataset.mb) el.style.setProperty("margin-bottom", applyUnit(el.dataset.mb), "important");
    if (el.dataset.mx) {
      const val = applyUnit(el.dataset.mx);
      el.style.setProperty("margin-left", val, "important");
      el.style.setProperty("margin-right", val, "important");
    }
    if (el.dataset.my) {
      const val = applyUnit(el.dataset.my);
      el.style.setProperty("margin-top", val, "important");
      el.style.setProperty("margin-bottom", val, "important");
    }

    if (el.dataset.p) el.style.setProperty("padding", applyUnit(el.dataset.p), "important");
    if (el.dataset.pt) el.style.setProperty("padding-top", applyUnit(el.dataset.pt), "important");
    if (el.dataset.pe) el.style.setProperty("padding-right", applyUnit(el.dataset.pe), "important");
    if (el.dataset.ps) el.style.setProperty("padding-left", applyUnit(el.dataset.ps), "important");
    if (el.dataset.pb) el.style.setProperty("padding-bottom", applyUnit(el.dataset.pb), "important");
    if (el.dataset.px) {
      const val = applyUnit(el.dataset.px);
      el.style.setProperty("padding-left", val, "important");
      el.style.setProperty("padding-right", val, "important");
    }
    if (el.dataset.py) {
      const val = applyUnit(el.dataset.py);
      el.style.setProperty("padding-top", val, "important");
      el.style.setProperty("padding-bottom", val, "important");
    }

    if (el.dataset.fs) {
      el.style.setProperty("font-size", applyUnit(el.dataset.fs), "important");
    }
  });
}

// Parse "-60" or "+60" for calc()
function parseOffset(value, defaultUnit) {
  const op = value.startsWith("-") ? "-" : "+";
  const cleanStr = value.replace(/^[-+]/, "");
  const hasCustomUnit = /[a-z%]/i.test(cleanStr);
  const val = hasCustomUnit ? cleanStr : `${cleanStr}${defaultUnit}`;
  return { op, val };
}

// Add 'px' if no unit is provided for margin/padding/font-size
function applyUnit(value) {
  const hasCustomUnit = /[a-z%]/i.test(value);
  return hasCustomUnit ? value : `${value}px`;
}

// Run on load
applyDynamicStyles();

// Re-run if new elements are added dynamically
const observer = new MutationObserver(() => applyDynamicStyles());
observer.observe(document.body, { childList: true, subtree: true });
Motivation and context

Bootstrap already uses data-bs-* attributes extensively. This proposal extends that convention to dynamic sizing and spacing values, reducing the need to write custom CSS or SCSS for one-off calc-based layouts and custom values that can't be expressed through existing utility classes.

Dominant language
MDX
Stars
175k
Forks
78.7k
Avg merge
1d 10h
Merged PRs (30d)
98

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from twbs/bootstrap

All issues in twbs/bootstrap

Similar issues

More Design issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.