29

Please consider the below snippet. i need to set multiple CSS properties in typescript. for that i have tried the below code.

public static setStyleAttribute(element: HTMLElement, attrs: { [key: string]: Object }): void {
        if (attrs !== undefined) {
            Object.keys(attrs).forEach((key: string) => {
                element.style[key] = attrs[key];
            });
        }
    }

for the above code i need to pass the parameters as

let elem: HTMLElement = document.getElementById('myDiv');
setStyleAttribute(elem, {font-size:'12px', color : 'red' , margin-top: '5px'});

But the above code throws error(tslint) as Element implicitly has an 'any' type because index expression is not of type 'number'. (property) HTMLElement.style: CSSStyleDeclaration.

Please help me !!!

7 Answers7

56

Try using setAttribute. TypeScript does not have the style property on Element.

element.setAttribute("style", "color:red; border: 1px solid blue;");

Some related discussion in this GitHub issue: https://github.com/Microsoft/TypeScript/issues/3263

theUtherSide
  • 3,338
  • 4
  • 36
  • 35
14

Just a little late to the party, but anyway...

The actual problem is not that style is not defined on Element. The word Element at the beginning of Element implicitly has an 'any' type because index expression is not of type 'number'. (property) HTMLElement.style: CSSStyleDeclaration is just the first word in a sentence and therefore uppercased. Means it does not relate in any way to the Element object - which is quite confusing.

However, the error message means that you are trying to access a property using the subscript operator [] with an incorrectly typed index. In your case your key is of type string but HTMLElement.style is a CSSStyleDeclaration object which has an index signature of [index: number]: string and consequently requires your key to be of type number.

The index signature comes from the typescript/lib/lib.dom.d.ts declaration file in your TypeScript installation. There you will find CSSStyleDeclaration.

So what you can do is simply cast to any like so:

(<any>element.style)[key] = attr[key];

It's not the best solution but it works and is straightforward. It also does not require you to stringify your styles like it would be necessary when you use element.setAttribute.

eddipedia
  • 401
  • 3
  • 6
  • 5
    BTW: Does anyone know why the `CSSStyleDeclaration` in TypeScript's declarations file has that number-based index signature instead of a string-based? Makes no sense to me. – eddipedia May 24 '18 at 09:49
  • 3
    It reflects the browser. Try: `myElement.style[0]` to access the first style of myElement. – HolgerJeromin Oct 19 '18 at 09:54
  • Here's the related issue on github https://github.com/microsoft/TypeScript/issues/17827 – user697576 Jul 01 '21 at 22:39
10

I hope this helps you or someone else...

You can achieve this using a HTLMDivElement and the CSSStyleDeclaration contained within it. eg.

var container: HTMLDivElement;

container.style.color = "red";
container.style.fontSize = "12px";
container.style.marginTop = "5px";

This also applies to other classes that inherit from HTMLElement and have a style property (for example HTMLBodyElement.

theUtherSide
  • 3,338
  • 4
  • 36
  • 35
ozOli
  • 1,414
  • 1
  • 18
  • 26
10

The API you were searching for is: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/setProperty

public static setStyleAttribute(element: HTMLElement, attrs: { [key: string]: string }): void {
    for(const [key, value] of Object.entries(attrs)) {
        element.style.setProperty(key, value);
    }
}

And hyphen is not allowed in object keys, so use ' here, too:

let elem: HTMLElement = document.getElementById('myDiv');
setStyleAttribute(elem, {'font-size':'12px', color: 'red', 'margin-top': '5px'});
HolgerJeromin
  • 2,201
  • 20
  • 21
  • 2
    This should be the accepted answer. TypeScript's CSSStyleDeclaration has number-based indexing (referenced in comments on other answers here) so string keys don't work. setProperty accepts string keys and has the same effect as `style[key] = val` without resorting to unsafe typing. Thanks @HolgerJeromin – evnp Feb 25 '21 at 16:23
  • This answer is useful, but `element.style.setProperty(key, attrs[key]);` will give an error since `attrs[key]` is an Object when the function expects a string. – qrsngky Jul 04 '23 at 02:01
  • Wow. All the years and no one found the wrong type in the function signature! Thanks! I fixed the signature and changed to a for-of loop. – HolgerJeromin Jul 04 '23 at 07:49
2

you can use this for a single element, and iterate over it to make it dynamic

let el: HTMLElement = document.getElementById('elementID');

el.style.height = "500px";
Ali
  • 1,633
  • 7
  • 35
  • 58
  • 1
    I've used this with TypeScript / Angular. Normally, `document.getElementById()` can return as an `Element` type, make sure you use `let el: HTMLElement = document.getElementById('elementID');` to change it. Thanks! – Geryson Jan 22 '22 at 17:19
2

This problem was post in 06 Jun 2016,Typescript 2.1RC was release in 09 Nov 2016 that had new feature to solve the problem

After reading Typescript handbook and declaration for dom style, I had found the key of this problem that missing string index signature in Typescript declaration for dom style like following code:

interface CSSStyleDeclaration {
  accentColor: string;
  alignContent: string;
  // ....
  [index: number]: string;
}

It should be like this (so we can resolve the problem):

interface CSSStyleDeclaration {
  accentColor?: string;
  alignContent?: string;
  // ....
  [index: number]: string;
  [propName: string]: string;
}

I had used Utility Types to create a new Type for style and it worked:

type styleDeclaration = Partial<CSSStyleDeclaration> & { [propName: string]: string };

If you wanna learn more about this, you can take a look at this demo.

type styleDeclaration = Partial<CSSStyleDeclaration> & { [propName: string]: string };

const dom = document.createElement('div');

const styleObj: styleDeclaration = { width: '100px', height: '200px' };

Object.keys(styleObj).forEach((styleKey: string) => {
  (dom.style as styleDeclaration)[styleKey] = styleObj[styleKey];
});
CarryOnHxy
  • 21
  • 2
1

An unsafe / untyped way:

const e = document.createElement("div")
Object.assign(e.style, {borderSize: "1rem", verticalAlign: "middle"})

You'll need to convert standard CSS style naming to the TypeScript alternatives for this to work. i.e. font-size vs. fontSize. Be warned: You will get no errors on a bad style name. {attrFOO: "bar"} is valid.

pestilence669
  • 5,698
  • 1
  • 23
  • 35