Fallback for css-vars - javascript

I want to use CSS vars the first time and am doing that
#circle_1 {
width: 50px;
height: 50px;
width: var(--size_1);
height: var(--size_1);
}
and fill it with JS like so
var input_1 = document.querySelector("#groesse_1");
var circle_1 = document.querySelector("#circle_1");
input_1.addEventListener("change", function() {
circle_1.style.setProperty("--size_1", input_1.value);
});
This works nice, but as long as the user doesn't add a value to input_1, the circles have a not defined size (which I tried to prevent by giving a default height/width in the CSS before I added the width: var(--size_1); thing)
How would I correctly add a default value to that element?
See here: https://codepen.io/daiaiai/pen/OQYwVW

CSS func var() accepts two arguments: the --var custom property, and a fallback value.
So to properly fallback values you would do
selector {
prop: 20px; /* for browser without support for variables */
prop: var(--my_var, 20px); /* for browser with support for variables */
}

You can give a fallback default value
#circle_1 {
width: var(--size_1, 30px);
height: var(--size_1, 30px);
}
So this way the default value its 30px but if --size_1 its not empty it will override the 30px
If you want to know more here vars on MDN
Here is your updated codepen with a fallback

You can do that when defining the variable, and you only supply width and height once:
#circle_1 {
--size_1: 50px;
width: var(--size_1);
height: var(--size_1);
}
In your event handler, you'll also need to specify units unless you're expecting the user to enter them, e.g.:
circle_1.style.setProperty("--size_1", input_1.value + "px");
// -------------------------------------------------^^^^^^^
...or similar.
More on MDN.
Live Example:
var input_1 = document.querySelector("#groesse_1");
var circle_1 = document.querySelector("#circle_1");
input_1.addEventListener("change", function() {
circle_1.style.setProperty("--size_1", input_1.value + "px");
});
#circle_1 {
--size_1: 50px;
width: var(--size_1);
height: var(--size_1);
border: 1px solid black;
}
<input id="groesse_1" type="text">
<div id="circle_1"></div>

Related

How to change a css value in javascript?

So I want to change a css value in javascript, without having an element in html, I'll explain like:
<style>
.box{
width: 10%;
}
</style>
<script>
// I want to change the width value of (.box) to something like "90%"
</script>
So what I mean to say is that I want to change the (.box) width value between the two style tags, I know my question sounds weird, but am just new coding and I really need it, any help appreciated!
Use media queries.
I don't remember the exact way to do this, but something like:
.box { width: 90%; }
#media screen and (min-width: 1000px) {
.box { width: 40%; }
}
You can change the properties (e.g. width) of a CSSStyleDeclaration with its setProperty() method.
You can get a CSSStyleSheet of a specific <style> element with its sheet property.
In our case, the stylesheet's first CSSStyleRule (sheet.cssRules[0]) is for the CSS class .box. You get the CSSStyleDeclaration object of a CSSStyleRule with its style property.
Example:
const iClass = document.getElementById("i-class");
const classRule = document.getElementById("my-style").sheet.cssRules[0];
// Set input.value to initial width-value (10%)
iClass.value = classRule.style.getPropertyValue("width");
// Update width-value on each input
iClass.addEventListener("input", () => {
classRule.style.setProperty("width", iClass.value);
});
/* Ignore; presentational styling */
.box {
margin-bottom: .5rem;
aspect-ratio: 1/1;
background-color: coral;
text-align: center;
}
<style id="my-style">
.box{
width: 10%;
}
</style>
<div>
<label for="i-class">Class width:</label> <input id="i-class">
</div>
<div class="box">class</div>
Unlike adding a new CSS rule, this changes the existing rule.
Here's one option, adding a <style> tag dynamically. This will add a style which overrides previous, obviously. See other answers for other options of changing existing rules.
var inline_style = `
.box {
width: 90%;
background: pink;
}`;
// from https://stackoverflow.com/a/28662118/3807365
document.head.insertAdjacentHTML("beforeend", '<style>' + inline_style + '</style>')
.box {
width: 10%;
background: blue;
}
<div class="box">i'm a box</div>

Change css class attribute values using javascript

I want to change the value of one of the attributes of css class dynamically
Here's my scenario:
I've many elements using one class, instead of getting them all and looping them over and applying style, I want to change the value of one of the attributes of class, which is alredy applied on them. for example
.prodName {
max-width: 270px;
display: block;
}
above class is being used by many elements, and I want to alter one of the attributes of that class like
.prodName {
max-width: 350px <---
display: block;
}
is there any simple method for this in javascript.
Before I post this question, I already searched but didn't find anything easy and useful.
thanks in advance to helping hands.
You can use CSS variables for this case.
const root = document.querySelector(':root');
function play() {
root.style.setProperty('--size', '300px');
}
:root {
--size: 100px;
}
.container {
background-color: red;
width: var(--size);
height: var(--size);
cursor: pointer;
}
<div class="container" onclick="play()"></div>
The only problem with the above approach is support in older browsers. If you have to support IE, and older browsers where CSS variable support is not present, you can handle this problem by adding a class to the body/parent container.
function play() {
document.body.classList.add('large')
}
.container {
background-color: red;
width: 100px;
height: 100px;
cursor: pointer;
}
.large .container {
width: 300px;
height: 300px;
}
<div class="container" onclick="play()"></div>
Add new class to CSS:
.mw350 {
max-width: 350px;
}
Then add new class to the element in JS:
document.querySelector('.prodName').className += ' mw350'; // <-- better to select using unique IDs, like '#prodNameElement'
If you are going to control the css class/attribute change from ts, maybe with a function or var change, you might want to use ngClass: https://www.freecodecamp.org/news/angular-ngclass-example/ and have all the logic where you want it, easily accessible.

Getting true dimensions of images with jquery on collected dom elements

I am trying to get the dimensions of images on a page for further use with a custom 'lightbox' or sorts. However, when trying both a pure js method, and a jquery method, I get the output undefined on my variables. Why is this? Is it because of jquery load event? I tried both onload and ready.
Basically I need the full dimensions of the image to justify whether it should be loaded in a lightbox with a click event or not.
Update I am now able to get console feedback from the function now, however it's not providing me a dimension of the image.
$('.postbody').find('img').each(function() {
var img = new Image(), width, height;
$(img).load(function() {
width = $(this).width();
height = $(this).height();
console.log('Width: '+width+' Height: '+height);
});
console.log($(this).attr('src'));
img.src = $(this).attr('src');
});
#theater-box {
display: none;
position: fixed;
width: auto;
height: auto;
min-width: 1005px;
max-width: 1428px;
padding: 10px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.90);
border: 2px solid rgba(255,255,255,0.4);
}
.postbody {
width: 90%;
height: 90%;
background: rgba(100,50,50,0.5);
}
.postbody * img {
width: 100%;
max-width: 1168px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="theater-box"></div>
<div class="postbody">
<div id="someclass"><img src="https://e8zzxa.bl3301.livefilestore.com/storageservice/passport/auth.aspx?sru=https:%2f%2fe8zzxa.bl3301.livefilestore.com%2fy2pDapooeiISgUV7-ugpyADuRULJ_stpkiALbypYJHjNxrhUqcvRsZ6eRk4PiJlClABLOfByjulDSDLOMCEpHhggVkgvM4z5Gdq0Jo-C0e1pCU%2fMajipoorHighlands2.jpg&wa=wsignin1.0" /></div>
</div>
You are setting the variables asynchronously and getting it directly.
In pseudocode it is a bit like this:
Set the function to retrieve the width and height when the images loads
Display the width and height variables (not set yet)
The functions set in step 1 runs and sets the varaibles.
So your code that uses the width and height should be inside the image.load function.
I hope it helps, if you have any further questions dont hesitate to comment :-)
Perhaps you can just put the console.log line as the last line in the $(img).load function.
Try this...
$(img).load = function() {
var $this = $(this);
width = $this.width();
height = $this.height();
}
I'm not exactly sure why the original method (which works in a lot of examples) was not working here. So I found some awesome code by GregL from right here at Stackoverflow.
Essentially, the method loads a new, and hidden image into the body, and then captures the width and height before removing it.
$('.postbody').find('img').each(function() {
var img = $(this), width, height,
hiddenImg = img.clone().css('visibility', 'hidden').removeAttr('height').removeAttr('width').appendTo('body');
width = hiddenImg.height();
height = hiddenImg.width();
hiddenImg.remove();
console.log('Width: '+width+' Height: '+height);
});
Check out the Fiddle

jQuery - set calculated div width

I tried to set on my page posts as cards to one div with id="content" (like on G+).
#content {
margin-top: 120px;
margin-bottom: 70px;
margin-left: auto ;
margin-right: auto ;
height: auto;
}
.card {
height: 250px;
width: 500px;
margin: 10px;
float: left;
}
and I want to calculate how much .card I can fit into the screen.
So I tried this:
$(document).ready(function () {
"use strict";
var cardAmount = (Math.floor($(window).width/520))*520;
$("#content").css("width", cardAmount);
});
but the problem is(I think) the second parameter of .css must by string and it's not.
The problem is most likely that you need to add a unit to this number so the CSS engine knows what to do with it.
Also, there's another problem with your code - your not calling width function here: $(window).width. Please remember that width is a function from jQuery API, not DOM API parameter that you can simply get like this. So the whole fix is quite simple:
var cardAmount = Math.floor($(window).width() / 520);
$("#content").css("width", cardAmount + "px");
Here - see how it works in this fiddle
I guess you are missing the syntax with the px or % in the css .
$("#content").css("width", cardAmount+"%");#or
$("#content").css("width", cardAmount+"px");#or
$("#content").css("width", cardAmount+"em");

How do I include an element's margin in the hot-spot for jQuery's hover() event?

jQuery(".my_container").hover(function(){
//do code
}, function(){
//do code
});
.my_container { width: 100px; height: 100px; margin: 50px; }
The code above doesn't react to mouse over of margin (margin isn't a part of element?) - how can I change that?
You could use a 50px transparent border instead - the margin isn't really supposed to be mouseable...
Include a pseudo element, e.g.
.my_container:before {
content:'';
position:absolute;
top:-50px;
bottom:-50px;
left:-50px;
right:-50px;
}
This adds an extra 50px to the existing element's clickable area.
If you only want to add this on touch screen devices, you could do this:
.touchevents .my_container:before {
...
}
This requires something like Modernizer to insert the appropriate feature-based CSS class.
Update
As per #Jaladh's comments, you may also need to apply position:relative to the container element, since position:absolute above will be relative to the first ancestor with a position attribute:
.my_container {
position:relative;
}
Perhaps use a 2nd wrapper element with padding on the outer element and existing background and padding styles on the inner element:
<div class="my_container">
<div class="my_container_inner">
<!-- etc. -->
</div>
</div>
jQuery(".my_container").hover(function(){
//do code
}, function(){
//do code
});
.my_container { padding: 50px; }
.my_container_inner { width: 100px; height: 100px; /* etc. */ }
Building upon #Dunc's solution, you can alternatively use pseudo element to mimic your container and let actual container behave like margins. This will look like:
.my_container {
width: calc(100px + (2 * 50px));
height: calc(100px + (2* 50px));
position: relative;
}
.my_container::before {
content: '';
position: absolute;
top: 50px;
bottom: 50px;
left: 50px;
right: 50px;
}
Also make sure to move all other properties (like background color, border, etc.) you had in my_container to my_container::before because before is acting like our container here.
This is essentially helpful if your containers are grid items and you want gaps in-between them to be hoverable, because otherwise using psuedo element to add margins won't work appropriately in that case.
Change the margin to padding and it'll be hoverable.

Categories