8

I'm building a UI library in JS that can, without relying on any CSS stylesheets, create UI components, stylised from code. So far, it's been quite easy, with exception of styling different control states (such as input:focus one).

Code that I use to create input field:

function newInput()
{
    var ctr = docmuent.createElement("input");
    ctr.setAttribute("type","text");
    ctr.setAttribute("value", some-default-value);
    ctr.style.fontFamily = "sans-serif,helvetica,verdana";
    /* some font setup here, like color, bold etc... */
    ctr.style.width = "256px";
    ctr.style.height = "32px";
    return ctr;
}

Styling it for default state is easy. However I am unsure how to set style for states such as focused, disabled or not-editable.

If I'd be having CSS stylesheets included in the project that would be easily sorted out. However I can't have any CSS files included, it must be pure JS.

Does anyone know how to set style for an input field state (eg. input:focus) straight from JS code?

No JQuery please :-) Just straight-up JS.

Thanks in advance!

6 Answers 6

8

You would need to add an event listener to the element in order to change the style of it. Here is a very basic example.

var input = document.getElementById("something");
input.addEventListener("focus", function () {
  this.style.backgroundColor = "red";  
});
<input type="text" id="something" />

Sign up to request clarification or add additional context in comments.

5 Comments

Did you mean: input.addEventListener?
I may have meant that :P
Thanks. Both provided answers (the one below) give solution, but I can only accept one, and I've decided to go with yours since it avoids adding CSS in run-time to header.
Unfortunately, this approach will not address the focus pseudo selector, but will instead update the background of the element when the focus event has been triggered. The only solution that will work here is @karthik's solution below, since it will allow selecting the focus pseudo selector.
Both question and answer are nearly 5 years old. Let it rest in peace. I'm sure OP has found a better solution or abandoned the project in these years :)
5

Other alternative would be to build a stylesheet for the page.

Something like this:

 var styles='input:focus {background-color:red}';

 var styleTag=document.createElement('style');
 if (styleTag.styleSheet)
     styleTag.styleSheet.cssText=styles;
 else 
     styleTag.appendChild(document.createTextNode(styles));

 document.getElementsByTagName('head')[0].appendChild(styleTag);

This way you will have clean separation of css styles from the scripts and so the better maintenance.

9 Comments

Understood. However does this mean that it's set for all input fields that will be created? Is there a way to make style for each input field separately, in case there's need for different styling for each input field?
you can change the css accordingly. you can go by element id or a class
OK understood. Thanks. And when control is to be removed from UI, how can I remove it's style? So it won't pile up in the head.
This approach helps you continue the typical dev cycle of writing html, scripts and css, where you update your css whenever the markup goes through the change. Since we don't have the luxury of CSS here, We could keep the JS code readable and maintenable as there is a separation in the styles and scripts. Infact you can put all the styles together in one file and have it included in the page.
I agree that it's better to keep CSS and JS separated, but for this one client demands it all be in JS. Just to clarify, how can I then remove styleTag that is added to head using your approach, when control (input) is removed/disposed?
|
5

Use CSS Variables if possible

It's 2022 and there are simpler solutions to this problem than adding event listeners all over the place that may never get cleaned up.

Instead if you have control over the CSS, do this:

.my-class {
  --focusHeight: 32px;
  --focusWidth: 256px;
}

.my-class:focus {
  height: var(--focusHeight);
  width: var(--focusWidth);
}

Then in your JavaScript it's as simple as using setProperty to update the variables:

const el = document.getElementById('elementId');
el.style.setProperty('--focusHeight', newFocusHeight);
el.style.setProperty('--focusWidth', newFocusWidth);

3 Comments

The only problem with this is browser support on China mobile devices, where WeChat internal browser (QQ) does not still supports it. So if you're developing for non-China market, is great solution to go for. But if you need it to work in WeChat internal browser (Android devices), need to be aware of this issue.
@Siniša this is true if you need to support extremely outdated browsers, but the question should also be asked of the business why you're still supporting these old browsers and how might you migrate users to more secure and modern browsers. caniuse.com/css-variables
Wish that was possible. If you develop for China market, there's no option to say "we don't support WeChat". No business for you if you do that. WeChat is used by probably 80% of advertising market for pushing html based campaigns (eg. mini web games, gamified experiences etc). Until Tencent updates their QQ browser (used by WeChat as internal browser, as a replacement to Chromium they used years ago). will need to deal with issues like this.
1

At first, create your input:

<input type="text" id="myElementID" />

Then add the javascript the following javascript:

const element = document.getElementById("myElementID");

// Add a box shadow on focus
element.addEventListener("focus", (e) => {
  e.target.style.boxShadow = "0 0 0 3px #006bff40";
});

// Remove the box shadow when the user doesn't focus anymore
element.addEventListener("blur", (e) => {
  e.target.style.boxShadow = "";
});

Comments

0

A quick oneliner, which dynamically appends a style tag to the body.

document.body.innerHTML += '<style>#foo:focus {background-color:gold}</style>'
<input id="foo"/>

Comments

-1

let input = document.querySelector(".input-text");
    let label = document.querySelector('.fields-label');
    input.addEventListener('focus', function(e){
        label.classList.add('is-active');
    })
    input.addEventListener('blur', function(e){
        if(input.value === "") {
            label.classList.remove('is-active');
        }
    })
     label.is-active{
            color:red;
        }
 
    <div class="input-fields">
        <label class="fields-label">Last Name</label>
        <input type="text" class="input-text">
    </div>

    

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.