Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

173
Views
Javascript advanced string search, find the closing curly brace

I have a some Javascript which creates and maintains a string of CSS, for example:

".joe{top:1rem} @media(min-width: 64rem){ .blogs{top:3rem} }"

Part of the logic can add a new CSS rule inside a @media query. Currently, it adds the rule after the opening { bracket of the @media query, because it's quite easy to search for @media(min-width: 64rem){ and then insert at that index, for example:

".joe{top:1rem} @media(min-width: 64rem){ .new{top:3rem} .blogs{top:3rem} }"

Here's a snippet of the logic:

// find the existing media query from the style tag
// styleTagCache is the CSS string being maintained
const searchString = `@media(min-width:${breakpoint}){`;
const mqIndex = styleTagCache.indexOf(searchString) + searchString.length;

//  insert rule into the media query
const styleTagArray = [...styleTagCache];
styleTagArray.splice(mqIndex, 0, ruleString);
styleTagCache = styleTagArray.join('');

However, I'd like to insert the new rule at the end of the media query, before its closing } bracket, like this:

".joe{top:1rem} @media(min-width: 64rem){ .blogs{top:3rem} .new{top:3rem} }"

I've had a few futile attempts, but can't figure it out. The difficult part seems to be searching for the media query's closing }, but ignoring any other } which are part of the CSS rules inside it.

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

You can iterate over the string after the occurrence of the media query to find the closing curly bracket and then insert the new rule:

const css = ".joe{top:1rem} @media(min-width: 64rem){ .blogs{top:3rem} }";
console.log(add(css, '64rem', '.new{top:3rem}'))

function add(css, breakpoint, rule) {
    const niddle = `@media(min-width: ${breakpoint}){`;
    let index = css.indexOf(niddle);
  if (index === -1)
    throw new Error('Media query not found');
   
  index += niddle.length;
  
  let balance = 0, pos = null;
  for (let i=index; i<css.length; i++) {
      const char = css[i];
    if (char === '{')
        balance++;
    else if (char === '}') 
        balance--;
      
    if (balance === -1) {
        pos = i-1;
      break;
    }
  }
  if (pos === null)
    throw new Error('Invalid css');
  return css.substring(0, pos) + ` ${rule} ` + css.substring(pos);
}

about 4 years ago · Juan Pablo Isaza Report

0

I don't know if this is interesting to you, but you can actually traverse all the CSS rules in JavaScript. So, here I find and print out the background color for a condition and add a new property (the border).

Depending on the complexity of you code it is not an easy task to find the right CSS rule and modify it, but it can be done...

var cssRules = document.styleSheets[0].cssRules;

// printout the background-color:
console.log([...cssRules].filter(r => r.conditionText == '(min-width: 10rem)')[0].cssRules[0].style.backgroundColor);

// add or modify a rule:
[...cssRules].filter(r => r.conditionText == '(min-width: 10rem)')[0].cssRules[0].style.border = 'black solid 5px';
@media(min-width: 10rem) {
  .new {
    background-color: red;
  }
}
<div class="new">new</div>

about 4 years ago · Juan Pablo Isaza Report

0

I think that it would make sense to maintain an object that holds all the properties of that @media rule. Then you can add more selectors on the fly and render the string again using the function.

The object I created is simple. You can make a more advanced object if needed.

const renderrule = rule => {
  let selectorsstr = rule.selectors.map(s => `${s.selector}{${s.props}}`).join(' ');
  return `@media{(${rule.condition}) ${selectorsstr}}`;
};

var mediarule = {
  condition: 'min-width: 64rem',
  selectors: [{
      selector: '.blogs',
      props: 'top:3rem'
    },
    {
      selector: '.new',
      props: 'top:3rem'
    }
  ]
};

console.log(renderrule(mediarule));

// adding to the rule:
mediarule.selectors.push({selector: '.new2', props: 'top:2rem'});

console.log(renderrule(mediarule));

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!