Skip to content

React Tutorial JSX and Components

JSX Attributes: className, style and More

Lesson 21 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

Attributes in JSX look like HTML attributes, but they turn into props (properties) passed to an element or component. This lesson covers the cases you will meet every day.

String values and expression values

Use quotes for a fixed string, and braces for anything calculated:

App.jsx
JSX
function App() {
  const user = { name: "Ada", avatar: "https://example.com/ada.png" };
  return (
    <section>
      <h2 title="A fixed string">{user.name}'s profile</h2>
      <a href={"https://example.com/users/" + user.name.toLowerCase()}>Open profile</a>
    </section>
  );
}

Do not put quotes around braces. src="{url}" passes the literal text {url}; src={url} passes the value of url.

className, not class

class is a reserved word in JavaScript, so JSX uses className:

App.jsx
JSX
function App() {
  return (
    <div>
      <style>{`.box { padding: 12px; background: #fff3e0; border-radius: 8px; }`}</style>
      <div className="box">Styled box</div>
    </div>
  );
}

(We put a <style> element in the example to keep it in one file. In a project you would import a CSS file; see CSS Stylesheets.)

htmlFor, not for

for is also reserved, so a <label> uses htmlFor to point at the input’s id:

App.jsx
JSX
function App() {
  return (
    <div>
      <label htmlFor="email">Email</label>
      <input id="email" type="email" />
    </div>
  );
}

The style attribute takes an object

In HTML, style is a string. In JSX it is a JavaScript object with camelCase keys. That is why you see two pairs of braces: the outer pair opens JavaScript, the inner pair is the object.

App.jsx
JSX
function App() {
  return (
    <p style={{ color: "white", backgroundColor: "#c0392b", padding: "8px 12px", fontSize: 18 }}>
      Warning!
    </p>
  );
}

Numbers become px for most properties (fontSize: 18 is 18px). Properties that are not lengths, such as opacity or lineHeight, stay unitless.

Boolean attributes

Writing the name alone means true. Passing false removes the attribute:

App.jsx
JSX
function App() {
  const locked = true;
  return (
    <div>
      <input aria-label="Name" placeholder="Editable" />
      <input aria-label="Locked" placeholder="Disabled" disabled />
      <button disabled={locked}>Disabled</button>
    </div>
  );
}

data- and aria- attributes keep their hyphens

App.jsx
JSX
<button data-testid="save" aria-label="Save changes">Save</button>

Always give icon-only buttons an aria-label, so screen readers know what they do.

Spreading attributes

If you have an object of props, spread it with {...object}:

App.jsx
JSX
function App() {
  const common = { type: "button", className: "btn", title: "Click me" };
  return <button {...common}>Spread button</button>;
}

Use spread with care. It is convenient, but it makes it harder to see what a component receives. Passing Props returns to this.

Event attributes take functions

App.jsx
JSX
function App() {
  const [message, setMessage] = React.useState("");
  return (
    <div>
      <button onClick={() => setMessage("Hi!")}>Say hi</button>
      <p>{message}</p>
    </div>
  );
}

Pass the function itself: onClick={handleClick}. Do not call it: onClick={handleClick()} runs it during rendering. Click Events explains this.

Common mistakes

  • class and for instead of className and htmlFor.
  • style="color: red" (a string) instead of style={{ color: "red" }}.
  • Quotes around braces: value="{count}".
  • CSS property names in kebab-case inside the style object: use backgroundColor, not background-color.

Key points

  • Quotes for fixed strings, braces for expressions.
  • className, htmlFor, camelCase events, and an object for style.
  • Boolean attributes: name alone is true; {false} removes it.