tldr;
JSX (React's language) is a superset of JavaScript (where class
is a reserved keyword), while Vue and Svelte both have templating languages which are supersets of HTML, thus allowing the use of class
as you would in HTML.
Speaking for Svelte here.
First, let's fix the false premise:
JavaScript frameworks like React and Svelte don't allow developers to use the class property on a virtual DOM element because the class keyword is reserved in JavaScript.
Svelte does allow the class
keyword, both on elements and components. You just have to work within the applicable constraints. We're coming back to this.
Let's start with React. Well, JSX actually. JSX is a strict superset of JS. Let's refer to this nice explanation. JSX is a superset of JS both syntactically (any JS program is valid JSX) and semantically (any JS program behaves the same when interpreted as JSX).
In order to be so, JSX has to respect every constraints of JS, of which "class is a reserved keyword". That's why React doesn't allow the class
keyword.
Note that this is not a technical constraints. React could reinterpret the class
keyword and make it work in JSX. But that would make JSX not strictly a superset of JS. Why? Because then, in some cases, the same JS code would not behave the same when interpreted as pure JS or as JSX (namely, having a variable named class
must crash to be JS).
This is a philosophical constraint. At one point, JSX developers must have weighted the inconvenience of not being able to use the class
keyword against suddenly not being a strict superset of JS. On one hand, you gain one little nicety, on the other you abruptly downgrade from being a mathematically pure superset to being just "yet another random template language".
It's easy to feel the strong mathematical incline that emanates from React, with its emphasis on pure functions, the "view as a function of the state", unidirectional data flows, etc. This is actually a very important taking from React. They imported a lot of benefits from mathematics into everyday application development. And so, quite understandably (to me), this group of developers favored (favors) purity over minor conveniences.
Being a superset of JS does bring many advantages. Even if you know nothing of JSX, you can write some immediately by using your existing JS knowledge. As long as you don't start using JSX extra features, you can predict all the behaviours of your code, because everything will behave the same.
Now, to the Svelte specifics... Svelte does not use JSX (and neither Vue in most cases, as far as I know). They use their own templating language. Not sure for Vue, but for Svelte it is a superset, not of JS, but of HTML. Rich Harris, creator of Svelte, once called that HTMLX in a talk (not sure how official this terminology currently is). Personally, this is one of the main reason why I'm so comfortable with Svelte. I find it cumbersome to write HTML is JS, while writing natural looking HTML(X) to, in the end, produce HTML feels just... Natural! But I digress...
So, the thing is Svelte too has to play within the limits of its own chosen laws. There are 2 of them that are relevant to the matter at hand. Both makes sense, and both can be worked around.
But first, to clear any misconception, Svelte does allow the use of the class
keyword for native elements (as opposed to Svelte components):
<div class="whatever">No problem with that</div>
It wouldn't be a proper superset of HTML if it didn't.
In this context, class
is actually a "directive", meaning it has added power, as compared to a pure HTML class. For example:
<script>
let blue = true
</script>
<!-- will render as: <div class="blue"></div> -->
<div class:blue />
<!-- will render as: <div class="red"></div> -->
<div class:red={blue} />
<!-- you can have several of them too... -->
<div class="foo" class:red class:blue />
So Svelte allows the use of the class
keyword, there's no doubt about that. For native elements that is.
Now, for components the story is a bit different. Here come the 2 laws I have mentioned earlier.
The first one is that Svelte components do not enforce having a single root elements. Or any elements at all, for that matter.
<script>
console.log('I am a valid Svelte component with no elements')
</script>
<!-- no code omitted -->
<p>I am a valid Svelte component</p>
<p>Too.</p>
The consequence of this is that Svelte can't know for sure to what element(s) it should automatically apply a class
set on the encompassing component. And so, in this situation, it doesn't do anything. It hands the controls back to you.
That doesn't mean that you can't implement it if you want. You just have to abide by our second law: the code inside the <script>
tag of a Svelte component has to be valid JS. Here again, this is not a technical limitation, but a philosophical one. It has been reiterated again and again by Svelte's creator and core developers on many occasions. On the syntax level, we're not even speaking of a superset anymore, but of equality. Any Svelte JS is valid JS (note the members of the relation have been swapped, as compared to "any JS is valid JSX").
On the other hand, Svelte JS is not a semantic superset of JS either. Some JS programs wont behave the same when interpreted as pure JS as when interpreted with Svelte, because Svelte overloads some constructs (like $:
or export let prop
) with a different meaning.
This constraint impacts us here because class
is not a valid variable name is JS, and Svelte components' properties are defined as JS variables. However you can bypass it:
<script>
// can't do, not valid JS:
// export let class
// but:
let cls = ''
export { cls as class } // valid JS
</script>
<div class={class} />
This component would be then used like this (live example):
<script>
import MyComponent from './MyComponent.svelte'
</script>
<MyComponent class="blue" />
So you can also use the class
keyword for components in Svelte.
Phew. Hope you enjoy a developed answer!
To sum it up, if some of the major frameworks allow the use of the class
keyword and some don't, it is for philosophical reasons. It makes full sense for JSX, as a superset of JS, to respect this constraint. It would make no sense for Svelte's HTMLX to implement this constraint for no reasons (and to stop being a superset of HTML in the process). Further, React has a stronger focus on mathematics purity, and Svelte has a stronger focus on code expressiveness and convenience. As always with good software, it's all in the trade-off!