Change Font Family Based On Other CSS Value - javascript

I am trying to change the font-family of a class (.button) based on the font-family value of h6. I realize this can't be done with CSS, but couldn't find a solution directly through JS. I wish it were as easy applying the styles in a stylesheet, but the h6 value is gerenated dynamically by the user. Any ideas?
Thanks!

This is the easiest way to do it, since you're using jQuery.
Just for demonstration, you can see that the button takes the font of the H6 element after you click the button.
If you want this to happen immediately, remove the click() function by deleting the first and last line of the JS code (first code block).
$('.my-button').click( function(){
var font = $('.my-title').css("font-family");
var weight = $('.my-title').css("font-weight");
$('.my-button').css('font-family', font);
$('.my-button').css('font-weight', weight);
});
.my-title {
font-family: "Lucida Handwriting";
font-weight: bold;
}
.my-button {
font-family: Verdana;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h6 class="my-title">Hello World</h6>
<button class="my-button">Some Button</button>

Have the potential font-family styles pre-set up in classes ahead of time and then use if/then logic to set the correct class on the element. The cornerstone of this is the element.classList property and its .add() method.
// Get references to the elements we need to work with
let h6 = document.querySelector("h6");
let btn = document.querySelector("button.button");
// Use if/then/else logic to set the button class
if(h6.classList.contains("foo")){
btn.classList.add("newFoo");
} else if(h6.classList.contains("bar")){
btn.classList.add("newBar");
} else if(h6.classList.contains("baz")) {
btn.classList.add("newBaz");
}
/* Example of what the pre-existing classes might be: */
.foo { font-family:"Comic Sans MS"; font-size:2em; margin:.5em; }
/* New styles that will be used to override: */
.newFoo { font-family:"Times New Roman"; }
.newBar { font-family:sans-serif; }
.newBaz { font-family:monospace; }
<h6 class="foo">foo</h6>
<button class="button">Click Me!</button>

Your question isn't clear enough for me, but I tried to answer you with a more general solution for your problem!
In the demo below, I've created an input as if the user will type a value there, and a button with button id, and its font-size will be changed according to the value provided from the user within the input field
var sizeInput = document.querySelector("#sizeInput")
var myBtn = document.querySelector("#button")
var sizeFromTheUser
sizeInput.addEventListener("change", function() {
// Update the variable's value based on the changed value from the user
sizeFromTheUser = sizeInput.value
// Change the font-size based on the given value
switch(sizeFromTheUser) {
case "h1":
myBtn.style.fontSize = "2em"
break;
case "h2":
myBtn.style.fontSize = "1.5em"
break;
case "h3":
myBtn.style.fontSize = "1.17em"
break;
case "h4":
myBtn.style.fontSize = "1em"
break;
case "h5":
myBtn.style.fontSize = "0.83em"
break;
case "h6":
myBtn.style.fontSize = "0.75em"
break;
}
})
<input type="text" id="sizeInput" />
<button id="button">This is text!</button>
You can apply the same to the font-family property with different Switch cases that meets your needs, or even using a different logic, but I just gave you a generic example that might be helpful in your situation!

Related

Change color in a number of different divs that all share the same class

I have a site with a lot of different div. The thing they have in common is all share (besides their unique classes) a shared class. Lets just call it .changeClass.
What I am looking for is code with a button (or radio buttons) and by clicking the button, the background instance of all these divs will get the same one (which the .changeClass has). So the .changeClass will just be active when the button is toggled/clicked.
I am looking for a way to do this with pure javascript and no Jquery.
Sorry for being a noob :-)
In the solution below, clicking the <button> element will add/remove the class style .changeClass to all elements that have the class style .apply applied.
let button = document.getElementById('change');
let containers = document.getElementsByClassName('apply');
function changeButtonText() {
if(button.innerHTML === "Add")
button.innerHTML = "Remove";
else
button.innerHTML = "Add";
}
button.addEventListener('click', function() {
for(let index = 0 ; index < containers.length ; ++index)
containers[index].classList.toggle('changeClass');
changeButtonText();
});
div {
margin-top: 25px;
}
.apply {
border: 3px solid black;
}
.changeClass {
background-color: black;
color: white;
border: 3px solid red;
margin-top: 25px;
}
<button id="change">Add</button>
<div class="apply">1</div>
<div class="apply">2</div>
<div class="apply">3</div>
<div class="apply">4</div>
<div class="apply">5</div>
First lets get all divs that are on the DOM
const divs = document.getElementsByTagName("div");
You will have array of all the divs that are on the DOM. Then add your class to all of it. In order to do that, lets loop it.
divs.forEach(div => div.className += div.className + " changeClass");
Could this be what you are looking for?
In html:
<button onclick="changeColor('blue');">blue</button>
In JS
function changeColor(newColor) {
var elem = document.getElementsByClassName("changeClass");
elem.style.color = newColor;
}
The HTML color can be any color you would like it to be, just change they name from blue to any color or input a hex code.
We have multiple divs with the same class value
We have given a function to the button that we want the event to happen when it is clicked, using the onclick method. Now when we click the button, the function called myFunction will run.
HTML:
<div class="changeClass">Im Example Div</div>
<div class="changeClass">Me Too</div>
<button type="submit" onclick="myFunction()">Click To Change Div BgColors !
</button>
We must define myFunction as Javascript and change the background color.
We have defined a function called myFunction.
With the getElementsByClassName selector in our function, we got all the data with the class value changeClass in object format.
To add a background (or any css property) to all of these objects; We put the object in a for loop and now we split our elements.
We can now define a background color for our elements with the style.backgroundColor parameter.
JavaScript:
function myFunction(){
var divs = document.getElementsByClassName('changeClass');
for(var i=0; i< divs.length; i++){
divs[i].style.backgroundColor = 'red';
}
}
For more detailed information, you can refer to the resources: https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
Don't be sorry for being new at something and wanting to learn more!
So what you are saying is that the divs you want to change all have a common class of "changeClass". If this is the case then you want a function is passed an argument value of the color you want to be changed. Since all of your divs are static and you probably don't plan on changing, declare a variable outside of this function that has the following code
const divs = document.getElementsByClassName("changeClass")
Then, inside of the function, loop through all of the divs collected inside the variable "divs", or whatever you want to call it. Since "getElementsByClassName" returns a collection, it does not have the built in "foreach" and "map" methods. So you have to use a for loop preferably the following.
const divs = document.getElementsByClassName("changeClass");
function changeColor(color) {
for (let element of divs) {
element.style.backgroundColor = color;
}
}
I may have interpreted this wrong but I hope it helps
You may find using a CSS variable helpful.
For example:
function bg(color) {
document.body.style.setProperty('--bg', color);
}
body {
--bg: cyan;
}
.container {
display: flex;
gap: 1vw;
}
.container div {
width: 100px;
height: 100px;
background-color: black;
}
.container div.changeClass {
background-color: var(--bg);
}
<body>
<button onclick="bg( 'red');">Red</button>
<button onclick="bg( 'green');">Green</button>
<button onclick="bg( 'blue');">Blue</button>
<button onclick="bg( 'black');">Black</button>
<div class="container">
<div class="changeClass"></div>
<div class="changeClass"></div>
<div class="changeClass"></div>
<div></div>
<div class="changeClass"></div>
</div>
</body>
Then when one of the radio buttons is clicked it sets the variable --bg.
Here's a simple snippet:
First of all - thank you for all your replies. And yes I should have included code. I tried so many things that i just gave up at som point - got confused what was right code and what was just rubbish. So I appreciate so much that you all took time to answer me. This was my first post so now I know for the future. The answers I got all was possible ways to solve my problem - so thank you all. I will do better next time. You are awesome...
BTW - All solutions seems to work - but can only checkmark one of them as you know.
You can add or remove a class to change the colours of different div:
document.queryselector('.className').classList.add('classNamethatyouwanttoadd');
document.queryselector('.className').classList.remove('classNamethatyouwanttoadd');

Difference between className and classList

Which one of the following should be preferred under what circumstances?
btnElement.classList.add('btn');
btnElement.className = 'btn';
Using "classList", you can add or remove a class without affecting any
others the element may have. But if you assign "className", it will
wipe out any existing classes while adding the new one (or if you
assign an empty string it will wipe out all of them).
Assigning "className" can be a convenience for cases where you are
certain no other classes will be used on the element, but I would
normally use the "classList" methods exclusively.
And "classList" also has handy "toggle" and "replace" methods.
https://teamtreehouse.com/community/difference-between-classlist-and-classname
ClassList as the name suggest is the list of classes in an element.
If you have multiple classes on an element and you want to add/remove one without altering the rest you should use classList.
classList also provides methods like toggle which are really useful.
function toggleClass(){
let txt = document.querySelector("h2");
txt.classList.toggle("changebg");
}
.font-style {
font-family: sans-serif;
}
.changebg {
background-color: lightcoral;
}
<h2 class="font-style" >Hello World!</h2>
<button onclick='toggleClass()'>Toggle Background Class</button>
Using "classList", you can add or remove a class without affecting any others the element may have. But if you assign "className", it will wipe out any existing classes while adding the new one (or if you assign an empty string it will wipe out all of them)
classList
Using classList, you can add or remove a class without affecting any other classes the element may have.
So this is helpful for adding additional classes to an element that contain other classes.
classList has some handy methods like toggle and replace.
if (clicked) {
button.classList.add('clicked');
} else {
button.classList.remove('clicked');
}
Here if the button was clicked it will add the clicked class along with other classes the element may have and it will remove only the clicked class from the element.
className
If you use className, it will wipe out any existing classes while adding the new one (or if you assign an empty string it will wipe out all of them).
Using className can be convenience when you know this element will not use any other classes.
if (clicked) {
button.className = 'clicked';
} else {
button.className = '';
}
In this case, className will wipe all the classes the element may have and add clicked class to it. The empty string('') will wipe all the classes.
Conclusion
the recommendation would be to use className whenever possible.
Use classList when you need classList methods like toggle, replace, etc.
context https://dev.to/microrony/difference-between-classlist-and-classname-45j7
You can see the changes in JavaScript to apply same difference one with use of classList and other with className .
It will be clear from 1st btn only that classList add extra name in class while className replaces the whole class (only .border is applied) .
Further are different function of classList which cannot be achieved by className and at last 4 line of code is reduced to 1 liner with use of toggle .
So you should look to your needs : Like, if you want to completely replace the class property names than use className else you can use classList property with different methods .add() .remove() .replace() .toggle() to only have changes in specific without hampering all names of class
Instruction for below snippet : Reload the snippet when you click one button so that clear differences can be seen on next btns
var classList1 = document.getElementById("part1")
var classname2 = document.getElementById("part2")
function funcAdd() {
classList1.classList.add("border");
classname2.className = "border";
}
function funcRemove() {
classList1.classList.remove("color");
classname2.style.color = "black";
}
function funcReplace() {
classList1.classList.replace("background", "background1");
classname2.style.backgroundColor = "lightgreen";
}
function funcToggle() {
classList1.classList.toggle("color1");
if (classname2.style.color == "gold") {
classname2.style.color = "blue";
} else {
classname2.style.color = "gold";
}
}
.background {
background-color: red
}
.background1 {
background-color: lightgreen
}
.color {
color: blue
}
.font {
font-size: 24px;
}
.border {
border: 10px solid black
}
.color1 {
color: gold;
}
<div id="part1" class="background color font">classList</div>
<br><br><br>
<div id="part2" class="background color font">className</div>
<br><br><br>
<button onclick="funcAdd()">Add a border class</button>
<button onclick="funcRemove()">Remove a color class</button>
<button onclick="funcReplace()">Replace a background class</button>
<button onclick="funcToggle()">Toggle a color class</button>
<br><br>
I have just known one thing difference between className and classList. className returns string within they are names of the current element and classList also returns names but as an array.

EventListener Only Firing Once

still learning the basics of JS, working with EventListeners now. Trying to make a button that changes the color of text back and forth but I think I'm misunderstanding the nature of the method, or using it incorrectly. I don't believe it's a syntax issue.
I have the text and the button, both with Id's. I created variables for both elements. I add an event listener to the button, and defined the if else statement in the function. The "if" portion of the function executes without issue, but that's where it ends. Sorry in advance for the formatting I wasn't sure what made the most sense. Thanks!
Here's the HTML:
<h1 id="header"> Here's some text </h1>
<button id="button"> Change the Color </button>
CSS:
#header {
color: red;
}
And the JavaScript:
var header = document.getElementById("header");
var button = document.getElementById("button");
button.addEventListener("click", function() {
if (header.style.color = "red")
{header.style.color = "blue";}
else if (head.style.color = "blue")
{header.style.color = "red";
}
})
In JavaScript (and other languages) you need to use == to check for equality.
However, in JavaScript there is also ===. === is the strict equality operator, meaning it does not do type conversion. What does that mean? It means:
"5" == 5 // true, since "5" as a number is equal to 5, the literal number
"5" === 5 // false, since a string cannot equal a number
So in your if statements you should use == or === instead of just =.
Others have mentioned the use of = vs == vs === - which is definitely your problem, but you're also going to have other problems with comparing styles the way you are doing.
The style property is unique and cumbersome. You have the "style" property which is a property of the DOM node (just like href for anchors or type for inputs). Then you have styles which are applied from a stylesheet - either a <style> tag or external stylesheet file. Sometimes the two different styles sources are in conflict.
For style properties, you read the node.style.color property like you are doing. To get the actual color being applied to the node, you must use window.getComputedStyle(). Let me explain the difference by example:
const div = document.getElementById('foo')
div.style.color; //-> red
window.getComputedStyle(div).color; //-> rbg(0, 255, 0) - this is green!
#foo { color: green !important }
<div id="foo" style="color: red">Hello!</div>
Notice how we set red on the node itself, but green !important in the stylesheet. The !important will win, which is why the text is green. Furthermore, the browser converts the color name green to its RGB equivalent rgb(0, 255, 0). This can be tedious to reconcile. What I usually recommend is having multiple class names and switching between those on click:
var header = document.getElementById("header");
var button = document.getElementById("button");
button.addEventListener("click", function() {
if (header.classList.contains("red")) {
header.classList.remove("red")
header.classList.add("blue")
} else if (header.classList.contains("blue")) {
header.classList.remove("blue")
header.classList.add("red")
}
})
.red { color: red }
.blue { color: blue }
<h1 id="header" class="red"> Here's some text </h1>
<button id="button"> Change the Color </button>

Is there a way to point to document.styleSheets[].cssRules[] using a rule name?

I want to change a specific class-property-value using Javascript, but by the class-name itself and not with any integer as a pointer (cssRules[i]) or looping all classes to find the matching "selectorText" value.
This is for changing the readable on-screen language within the page.
<style id="languages" class="languages" title="languages">
<!--
/* ... more styles ... */
.lang-ita { display : none; }
.lang-eng { display : none; }
/* ... more styles ... */
-->
</style>
<script language="javascript">
<!--
function fxSwitchLanguage(i)
{
/* ... more code ... */
document.getElementById('languages').sheet.cssRules[i].style.setProperty('display','block');
/* ... more code ... */
}
-->
</script>
<button onClick="fxSwitchLanguage(0);">ITA</button>
<button onClick="fxSwitchLanguage(1);">ENG</button>
<br>
<div class="lang-ita">CIAO!</div>
<div class="lang-eng">HELLO!</div>
Of course I set the previous language "display" to "none" before showing only the new selected one.
I would like to have ".cssRules['.lang-eng']" instead of ".cssRules[i]".
Since this document is shared and may be changed by someone else, I really DO prefer to point the class using its name and not any hard-coded integer for obvious stability reasons, moreover I do not want to use a "for" cycle to test the "selectorText" property of each written class (can be easily thousands).
I don't mind any Browsers differences (.cssRules or .rules).
I just want to know if it is possible to have it in the way I'd prefer to.
No, there is no CSSOM API to get a rule (or list of rules) by its selector string. Iterating them to find one is the only way. Of course you wouldn't do this in the fxSwitchLanguage function, everytime it is called, but outside of it, only once when the script is loaded. Then just store references to the relevant rules in a few constants, or a data structure.
But since your goal is to manipulate the rules by JavaScript, I'd go even further and also create them using javascript. That way, you can easily store a reference to them without iteration.
const {sheet} = document.getElementById('languages');
const rules = new Map(['eng', 'ita', 'esp'].map(lang => {
const rule = sheet.cssRules[sheet.insertRule(`.lang-${lang} {
display: none;
}`)]; // yes, it's weird, `insertRule` returns an index
return [lang, rule];
}));
let active = null;
function fxSwitchLanguage(l) {
if (active) rules.get(active).style.display = 'none';
rules.get(l).style.display = 'block';
active = l;
} // or build a toggle or whatever
<style id="languages">
</style>
<button onClick="fxSwitchLanguage('ita');">ITA</button>
<button onClick="fxSwitchLanguage('eng');">ENG</button>
<button onClick="fxSwitchLanguage('esp');">ESP</button>
<br>
<div class="lang-ita">CIAO!</div>
<div class="lang-eng">HELLO!</div>
<div class="lang-esp">HOLA!</div>
from comment here is the idea :
function fxSwitchLanguage(varlang) {
//* test if already created and remove it before update*/
if (document.contains(document.getElementById("langSetting"))) {
document.getElementById("langSetting").remove();
}
//* update language chosen*/
var newStyle = document.createElement("style");
newStyle.setAttribute("id", "langSetting"); //* put a mark on it */
var addContent = ".lang-" + varlang + "{display:block;}";
newStyle.appendChild(document.createTextNode(addContent));
var head = document.getElementsByTagName("head")[0];
head.appendChild(newStyle);
}
[class^='lang'] {display:none;}
<button onClick="fxSwitchLanguage('ita');">ITA</button>
<button onClick="fxSwitchLanguage('eng');">ENG</button>
<hr>
<p class="lang-ita">CIAO!</p>
<div class="lang-eng">HELLO!</div>

How to dynamically change a class css styling?

Goal
In my program I want to do both things with jquery/javascript:
Change styling of css classes dynamically
Add/remove classes to elements
Problem
To do the first thing I use $(".className").css() method, but it changes style only for those elements that already have className class, i.e. if I later add className to an element its style won't be new. How can I solve this?
Example
See it also at jsfiddle.
$("p").addClass("redclass");
$(".redclass").css("color", "darkRed");
$("span").addClass("redclass");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>
Result:
A more shorten format:
$("<style/>", {text: ".redclass {color: darkRed;}"}).appendTo('head');
The snippet:
$("<style/>", {text: ".redclass {color: darkRed;}"}).appendTo('head');
$("p").addClass("redclass");
$("span").addClass("redclass");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>
While other (working) answers have been supplied, they don't actually answer your question - namely, they don't change the specified css class, but instead override it by adding another rule later in the document.
They achieve this, basically:
Before
.someClass
{
color: red;
}
After
.someClass
{
color: red;
}
.someClass
{
color: white;
}
When in many cases, a better option would see the color attribute of the existing rule altered.
Well, as it turns out - the browser maintains a collection of style-sheets, style-sheet rules and attributes of said rules. We may prefer instead, to find the existing rule and alter it. (We would certainly prefer a method that performed error checking over the one I present!)
The first console msg comes from the 1 instance of a #coords rule.
The next three come from the 3 instances of the .that rule
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
byId('goBtn').addEventListener('click', onGoBtnClicked, false);
}
function onGoBtnClicked(evt)
{
alterExistingCSSRuleAttrib('#coords', 'background-color', 'blue');
alterExistingCSSRuleAttrib('.that', 'color', 'red');
}
// useful for HtmlCollection, NodeList, String types (array-like types)
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
function alterExistingCSSRuleAttrib(selectorText, tgtAttribName, newValue)
{
var styleSheets = document.styleSheets;
forEach(styleSheets, styleSheetFunc);
function styleSheetFunc(CSSStyleSheet)
{
forEach(CSSStyleSheet.cssRules, cssRuleFunc);
}
function cssRuleFunc(rule)
{
if (selectorText.indexOf(rule.selectorText) != -1)
forEach(rule.style, cssRuleAttributeFunc);
function cssRuleAttributeFunc(attribName)
{
if (attribName == tgtAttribName)
{
rule.style[attribName] = newValue;
console.log('attribute replaced');
}
}
}
}
#coords
{
font-size: 0.75em;
width: 10em;
background-color: red;
}
.that
{
color: blue;
}
<style>.that{color: green;font-size: 3em;font-weight: bold;}</style>
<button id='goBtn'>Change css rules</button>
<div id='coords' class='that'>Test div</div>
<style>.that{color: blue;font-size: 2em;font-weight: bold;}</style>
#synthet1c has described the problem. My solution is:
$("head").append('<style></style>');
var element = $("head").children(':last');
element.html('.redclass{color: darkred;}');
What you are having issue with is that when you use the jQuery selector $('.redclass').css('color', 'darkRed') you are getting all the elements that currently have that class and using javascript to loop over the collection and set the style property.
You then set the class on the span after. Which was not included in the collection at the time of setting the color
You should set the class in your css file so it is distributed to all elements that have that class
console.log($('.redclass').length)
$("p").addClass("redclass");
console.log($('.redclass').length)
// $(".redclass").css("color", "darkRed");
$("span").addClass("redclass");
console.log($('.redclass').length)
.redclass {
color: darkRed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>

Categories

Resources