Home > Net >  How can I change the style of all <mark>snippets</mark> within html using javascript?
How can I change the style of all <mark>snippets</mark> within html using javascript?

Time:09-26

I have a static html file containing mostly text. Lots of text snippets are highlighted using the <mark> tag. I would like to add a button that toggles the text weight of the marked text snippets between bold and normal. The intended effect is to switch on / off the highlighting.

Is there any magic way to do it by directly changing the style of the mark css class?

Example:

  • HTML: ... This is an <mark>important text snippet</mark> ...
  • CSS class BEFORE I hit the button: mark { text-weight: bold; }
  • CSS class AFTER I hit the button: mark { text-weight: normal; }

The reason why I want to do this is to allow the user to decide, if he wants to see highlighted text or not. I know I can change the style of each marked text snippet, but I am wondering, if there is a more direct way.

CodePudding user response:

Method 1 - Toggling a Class on a Parent Element

A more direct way would be to add a class to a parent element. Then, in CSS, you can select all of the child mark elements. This method saves you from iterating over every mark element on your page in JS. You could add this class on a containing div or even on the root html element if you desire.

classList.toggle is supported on all major browsers: https://caniuse.com/?search=classlist.toggle

function toggleMarkup() {
  document.querySelector("#content").classList.toggle("markup-shown");
}
p.markup-shown mark {
  font-weight: bold;
}
<p id="content">
Hello! This is some <mark>marked up</mark> text! And this is some more <mark>marked</mark> text.
</p>

<button onclick="toggleMarkup()">
Click me to toggle markup.
</button>

Method 2 - Using CSSOM

https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model https://stackoverflow.com/a/55468693/9627251

You can also obtain and modify existing CSS classes directly from JS:

const rules = document.styleSheets.map(sheet => sheet.cssRules);
const rule = rules.find(r => r.selectorText == 'mark');
rule.style.fontWeight = 'bold'; // or normal, in your toggle function logic

Note that you would already have to have a CSS rule like:

mark { font-weight: normal; }

CodePudding user response:

Query all your mark elements, then toggle a highlight class to affect their font-weight styling. Get the parents of the mark elements using '.closest()', and add a button to each parent element.

const marks = document.querySelectorAll('mark')

// use event target to get the parent element and subsequent 
// mark element and toggle a class of normal font weight
function toggleHighlight(e) {
  e.target.closest('li').querySelectorAll('mark').forEach( el => {
    el.classList.toggle('normal')
  })
}

marks.forEach(mark => {
  // create the button
  const button = document.createElement('button')
  // add text for the button
  button.textContent = 'Toggle Highlight'
  // get the parent element your mark is living within and append the button to it
  // make sure it only gets one button in case there are more than one mark element
  !mark.parentNode.innerHTML.includes('button') ? mark.parentNode.appendChild(button) : null  
  // event listener for when the button is pressed 
  button.addEventListener('click', toggleHighlight)
})
mark {
  font-weight: bold;
}

.normal {
  font-weight: normal;
}

li {
  clear: left;
}

button {
  float: right;
}
<ul>
  <li>This is not important text</li><hr>
  <li><mark>This text here important text.</mark> But this is not. <mark>We have more important text here as well.</mark> Arcu cursus euismod quis viverra nibh cras pulvinar mattis. Tristique et egestas quis ipsum suspendisse ultrices gravida dictum. Ac turpis egestas integer eget. </li><hr>
  <li>This is text not important text. <mark>But this is</mark></li><hr>
  <li><mark>This text here important text.</mark> But this is not</li><hr>
</ul>

CodePudding user response:

What about something like this?

<html>
    <head>
        <style>
            mark {
                font-weight: bold;
                background: none;
            }
        </style>
    </head>
<body>

This is an <mark>important text snippet</mark> and so <mark>is this</mark>.

<button onclick = "changeMark()">Change Mark Style</button>

<script>
    function changeMark() {
        document.querySelectorAll("mark").forEach(e => e.style.fontWeight = "normal");
    }
</script>

</body>
</html>

CodePudding user response:

Sometimes I use this function :

function changeStyleProperty(ssIndex, selTxt, pName, pVal) {
    const cssRules = document.styleSheets[ssIndex].cssRules;
    for (let i = 0; i < cssRules.length; i  ) {
        if (cssRules[i].selectorText === selTxt) {
            cssRules[i].style.setProperty(pName, pVal);
        }
    }
}

You can use changeStyleProperty(ssIndex, 'mark', 'text-weight', 'bold') to bold, and then changeStyleProperty(ssIndex, 'mark', 'text-weight', 'normal') to change back.

(If you have only one stylesheet / style block then you can just use ssIndex=0, otherwise you might need to check [maybe with console.log(document.styleSheets);] and find out which stylesheet your mark rule is in.)

  • Related