0

I want to get style by writing classes.

  • If i write a class name "m-t-9" then it will add margin-top: 9px;.
  • If i write "m-t-13" then it will add margin-top: 13px;
  • If I write "m-t-m-12 then it will add margin-top: -12px; for me.

I want this kind of actions through pure JavaScript (Not jQuery). I tried a lot but failed. Can any one please let me know the js code for this?

7
  • You can create css classnames like you have above and give them the styles you want added. developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/… Commented Jun 28, 2021 at 21:44
  • 1
    Bootstrap has some classes that seem to act like this, you could see how it does it. Commented Jun 28, 2021 at 21:44
  • @mkaatman That would require creating dozens of classes, for every possible margin-top, margin-bottom, margin-left, and margin-right value. Commented Jun 28, 2021 at 21:45
  • VS code can do shortcuts like this that expand out. Commented Jun 28, 2021 at 21:46
  • 1
    @Barmar Less will compile to regular CSS, so OP will need to basically create for loops to create the CSS necessary. Not a big deal, but if they want JS to do this, they should show what was tried. Commented Jun 28, 2021 at 21:57

2 Answers 2

1

This can be done with an obj to define your rules for property, pos and unit. Then you run two functions, one that formats the style and the other that gathers the classes.

NOTE: This method uses the inline css in HTML to style elements with a parsed string set in the class attribute of elements.

The first function would get the class as a string and then using el.substring, decontruct it into its parts: prop pos and unit. We match the classObjs keys with the deconstructed parts of our passed in class string. Then we set the parts to the keys values.

prop: m => margin p => padding

pos:

  • l => left
  • r => right
  • t => top
  • b => bottom
  • n => ''

Unit: px

note: n would basically be something like: padding: 20px; no position, so: p-n-20

The second function will take the element/s we pass into it and set their respective styles to that of the class string we have in their class attribute using a regex match. I use two regex/s one for positive units and the other for negative units. So our potential classes would look like: m-l-30 => margin-left: 30px; or p-t-10 => padding-top: 10px; or m-b--20 => margin-bottom: -20px; or p-n-30 => padding: 30px;. Then the function gets the current inline style if present and then appends the new parsed style to the current style and sets the elements inline style to the concatonated string.

//get all elements inside .main
const test = document.querySelectorAll('.main *')

const classObj = {
  property: {
    m: "margin",
    p: "padding"
  },
  position: {
    t: "-top",
    b: "-bottom",
    l: "-left",
    r: "-right",
    n: ""
  },
  unit: "px"
}

function setStyleFromClass(str) {
  let styledClass = '';
  const prop = str.substring(0,1),
    pos = str.substring(2,3),
    unit = str.substring(4,str.length)
    
  for (keys in classObj) {
    if (typeof classObj[keys] === 'object') {
      if (prop in classObj[keys]) {
        styledClass += classObj[keys][prop]
      }
      if (pos in classObj[keys]) {
        styledClass += `${classObj[keys][pos]}:`
      }
    } else {
      styledClass += `${unit}px;`
    }

  }
  return styledClass;
}

function getEls(el) {
  const regex = /([m|p]{1}[\-]{1}[t|b|l|r|n]{1}[\-][0-9]+)/g
  if (el.length > 1) {
    // node list
    let classes = ''
    el.forEach(tag => {
      const classes = tag.getAttribute('class')
      let classArr = classes.split(' ')
      classArr.forEach(cls => {
        if(cls.match(regex)) {
          let style = setStyleFromClass(cls)
          let cur = tag.getAttribute('style')
          cur ?
            tag.setAttribute('style', `${cur} ${style}`) :
            tag.setAttribute('style', `${style}`)
        }
        if(cls.match(/([m|p]{1}[\-]{1}[t|b|l|r|n]{1}[\-][\-][0-9]+)/gm)) {
          let style = setStyleFromClass(cls)
          let cur = tag.getAttribute('style')
          cur ?
            tag.setAttribute('style', `${cur} ${style}`) :
            tag.setAttribute('style', `${style}`)
        }
      })
    })
  }
}

getEls(test)
.red {
  color: red;
}

.redbg {
  background-color: pink;
}
<div class="main">
  <div class="test red m-t-50 p-l-50">test div element -> m-t-150 margin-top: 150</div>
  <p class="test redbg m-b--10 p-n-20">test p element has a negative margin-bottom of 10px, should push next element up into border-box</p>
  <div id="testId" class="p-l-200">test element with padding right 200px</div>
</div>

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

Comments

1

Try this:

const options = {
  matchRegex: new RegExp('[m][-][t|l|b|r][-][0-9]+'),
  'm-t': {
    styleName: 'margin-top',
    affix: 'px',
    prefix: ''
  },
  'm-l': {
    styleName: 'margin-left',
    affix: 'px',
    prefix: ''
  },
  'm-b': {
    styleName: 'margin-bottom',
    affix: 'px',
    prefix: ''
  },
  'm-r': {
    styleName: 'margin-right',
    affix: 'px',
    prefix: ''
  }
}
document.querySelectorAll("*").forEach((e) => {
  e.classList.forEach((classname) => {
    if (options.matchRegex.test(classname)) {
      const li = classname.lastIndexOf('-');
      const type = classname.substring(0, li);
      const value = classname.substring(li + 1);
      const details = options[type];
      e.style[details.styleName] = details.prefix + value + details.affix;
    }
  })
})
<div class="m-t-50 m-b-50">
  Margin Top 50, Margin Bottom 50
</div>
<div class="m-t-10 m-l-20">
  Margin Top 10, Margin Left 20
</div>

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.