Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

80%
+6 −0
Q&A Change font-family with JavaScript

To do that, you could change the selector from body to *, as the other answer said. By selecting only body, it won't change child elements that has defined a more specific rule, and that's why you ...

posted 2y ago by hkotsubo‭  ·  edited 2y ago by hkotsubo‭

Answer
#4: Post edited by user avatar hkotsubo‭ · 2021-11-12T14:13:24Z (over 2 years ago)
some "future-proof" stuff
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). By selecting only `body`, it won't change child elements that has defined a more specific rule, and that's why you need to set the style for all of them.
  • But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • Just in case the site's layout change in the future, here's an image of the current icons:
  • ![Icons for Inbox and Mobile Sign In, as they were in November 2021](https://software.codidact.com/uploads/EdaCVirumjWig6yi7Ni51kfd)
  • The current HTML for this (in November 2021) is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). By selecting only `body`, it won't change child elements that has defined a more specific rule, and that's why you need to set the style for all of them.
  • But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • Just in case the site's layout change in the future, here's an image of the current icons (in November 2021):
  • ![Icons for Inbox and Mobile Sign In, as they were in November 2021](https://software.codidact.com/uploads/EdaCVirumjWig6yi7Ni51kfd)
  • The HTML for this is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
#3: Post edited by user avatar hkotsubo‭ · 2021-11-12T14:12:05Z (over 2 years ago)
some "future-proof" stuff
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). By selecting only `body`, it won't change child elements that has defined a more specific rule, and that's why you need to set the style for all of them.
  • But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • The HTML for this is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). By selecting only `body`, it won't change child elements that has defined a more specific rule, and that's why you need to set the style for all of them.
  • But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • Just in case the site's layout change in the future, here's an image of the current icons:
  • ![Icons for Inbox and Mobile Sign In, as they were in November 2021](https://software.codidact.com/uploads/EdaCVirumjWig6yi7Ni51kfd)
  • The current HTML for this (in November 2021) is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
#2: Post edited by user avatar hkotsubo‭ · 2021-11-12T13:57:47Z (over 2 years ago)
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • The HTML for this is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
  • To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). By selecting only `body`, it won't change child elements that has defined a more specific rule, and that's why you need to set the style for all of them.
  • But there are some corner cases that I think it's worth exploring.
  • ---
  • # Not everything needs to be selected
  • Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).
  • Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?
  • Instead, you could limit the selection only to elements inside the document's body:
  • ```javascript
  • // select descendants of body instead of the whole document
  • document.body.querySelectorAll("*").forEach((e) => {
  • e.style.fontFamily = "Arial";
  • });
  • ```
  • This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.
  • And of course this excludes `body` itself, which can be included with a little extra code:
  • ```javascript
  • // change style of body and its descendants
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • }
  • ```
  • I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.
  • ---
  • # Some things might break
  • Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • The HTML for this is:
  • ```html
  • <i class="fas fa-fw fa-inbox" title="Notifications"></i>
  • <i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
  • ```
  • And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:
  • ![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)
  • <sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>
  • So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).
  • Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.
  • ---
  • # Pseudo-elements
  • The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:
  • ```html
  • <p>Abc</p>
  • ```
  • And this CSS:
  • ```css
  • p {
  • font-family: monospace;
  • font-size: 50px;
  • }
  • p:first-letter {
  • font-family: Times;
  • }
  • p:after {
  • font-family: Times;
  • content: "xyz";
  • }
  • ```
  • The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.
  • ![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)
  • After running the JavaScript code above, only "bc" will be changed to Arial:
  • ![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)
  • That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.
  • In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):
  • ```javascript
  • // include here all pseudo elements you want to check
  • const pseudoElements = ['first-letter', 'after', 'before'];
  • for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
  • e.style.fontFamily = "Arial";
  • // check pseudo elements
  • for (const psEl of pseudoElements) {
  • var style = window.getComputedStyle(e, `::${psEl}`);
  • if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
  • // computed style is read-only, so we must change it like this
  • const sheet = document.styleSheets[0];
  • // insert rule at the end, so it overwrites any others
  • sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
  • }
  • }
  • }
  • ```
  • With that, all elements and pseudo-elements are updated to Arial:
  • ![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)
  • Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.
#1: Initial revision by user avatar hkotsubo‭ · 2021-11-12T13:53:27Z (over 2 years ago)
To do that, you could change the selector from `body` to `*`, [as the other answer said](https://software.codidact.com/posts/284842/284844#answer-284844). But there are some corner cases that I think it's worth exploring.

---
# Not everything needs to be selected

Although `document.querySelectorAll("*")` works, I think it's overkill. By selecting everything, you'll be changing the style of elements that don't need to, such as `head`, `title`, `meta`, `script`, and many others for which changing the font is pointless (for example, `title` is showed only in the browser tab and you can't change its style, `meta` doesn't have rendered content and there's no point in changing its font, etc).

Of course setting the font family for those elements doesn't cause errors, but it has no effects at all. And why doing something that will have no effect?

Instead, you could limit the selection only to elements inside the document's body:

```javascript
// select descendants of body instead of the whole document
document.body.querySelectorAll("*").forEach((e) => {
    e.style.fontFamily = "Arial";
});
```

This eliminates most elements that don't need to be styled (such as "everything inside `head`"). That will still select "non-text" elements inside `body` (such as `script`), though.

And of course this excludes `body` itself, which can be included with a little extra code:

```javascript
// change style of body and its descendants
for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
    e.style.fontFamily = "Arial";
}
```

I basically created an array containing `body` and its descendants, and I also changed from `forEach` to `for..of`, just to show another way of looping through the elements.

---

# Some things might break

Maybe it's not your case, but many sites today use things like [Font Awesome](https://fontawesome.com/), which provides a "font" with glyphs that are like images. Codidact uses it in many places, such as the icons on the top bar:

<i class="fas fa-fw fa-inbox" title="Notifications"></i>
<i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>

The HTML for this is:

```html
<i class="fas fa-fw fa-inbox" title="Notifications"></i>
<i class="fas fa-fw fa-mobile-alt" aria-label="Mobile Sign In" title="Mobile Sign In"></i>
```

And all the icons in the bar are similar. If you check them in browser's console, you'll see that the element's font-family is "Font Awesome 5 Free". If I change it to "Arial", the icons are not displayed anymore:

![Top bar with icons not displayed after changing font family to Arial](https://software.codidact.com/uploads/8TYp9di7k76ib2ZurMLF5MVz)

<sup>That's because Font Awesome uses code points in the [Private Use Area](https://codepoints.net/private_use_area), for which many fonts don't have the respective glyphs.</sup>

So inside the loop you must also check if there are elements that you don't want to change (the criteria will vary on a case by case basis). Or you can use a more complex selector to exclude what you don't want (such as `document.body.querySelectorAll("*:not(i)")` to exclude `i` tags).

Obviously, if your page doesn't have such cases and changing the font for all elements is fine, using `*` will do the job.

---
# Pseudo-elements

The solution above doesn't work for CSS pseudo-elements, such as `::first-letter`, `::after`, `::before`, etc. For example, given this HTML:

```html
<p>Abc</p>
```
And this CSS:
```css
p {
  font-family: monospace;
  font-size: 50px;
}
p:first-letter {
  font-family: Times;
}
p:after {
  font-family: Times;
  content: "xyz";
}
```

The letter "A" and the text "xyz" will be displayed with "Times" font, while "bc" will have a monospaced font.

![First letter and "xyz" with Times, paragraph with monospace](https://software.codidact.com/uploads/xhugxeCGLyM2Lo7LWCSRt1EF)

After running the JavaScript code above, only "bc" will be changed to Arial:

![Paragraph set to Arial, but pseudo elements didn't change](https://software.codidact.com/uploads/rfF5c1gsqn7rHrHEtC4hXAxe)

That's because `querySelectorAll` doesn't select nor return pseudo-elements. So `::first-letter` and `::after` remain with their original fonts.

In that case, you can use [`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) to check for pseudo-elements styles, and change them accordingly. Unfortunately, `getComputedStyle` returns a read-only object, so we can't change it directly. One solution is to add a style directly in the document, by using [`insertRule`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule):

```javascript
// include here all pseudo elements you want to check
const pseudoElements = ['first-letter', 'after', 'before'];

for (const e of [ document.body, ...document.body.querySelectorAll("*") ]) {
    e.style.fontFamily = "Arial";
    // check pseudo elements
    for (const psEl of pseudoElements) {
        var style = window.getComputedStyle(e, `::${psEl}`);
        if (style.fontFamily !== 'Arial') { // if font family is not Arial, change it
            // computed style is read-only, so we must change it like this
            const sheet = document.styleSheets[0];
            // insert rule at the end, so it overwrites any others
            sheet.insertRule(`${e.tagName.toLowerCase()}::${psEl} { font-family: Arial }`, sheet.cssRules.length);
        }
    }
}
```

With that, all elements and pseudo-elements are updated to Arial:

![All text in Arial](https://software.codidact.com/uploads/F7xmAbcKMGP4tV5fiEFBmbYM)


Again: if you don't have any pseudo-elements that need to be changed, all this work is not needed. I just wanted to cover more possible cases, because "changing all elements" is not always that simple.