JSX attributes are used to provide additional information to HTML elements and React components. They allow you to control how an element behaves, looks, and receives data.
If you already understand HTML attributes such as class, id, src, href, and alt, JSX attributes will feel familiar. However, JSX follows JavaScript and React conventions, so some attribute names and value formats are different from regular HTML.
For example, HTML uses:
<img src="profile.jpg" alt="Profile">
The same element in JSX is written as:
<img src="profile.jpg" alt="Profile" />
JSX also allows attribute values to come from JavaScript:
const imageUrl = "/profile.jpg";
<img src={imageUrl} alt="Profile" />
This ability to make attributes dynamic is one of the most useful features of JSX.
What Are JSX Attributes?
An attribute provides additional information to an element.
In HTML:
<button disabled>Submit</button>
disabled is an attribute.
In JSX:
<button disabled>Submit</button>
disabled is also an attribute.
Attributes can describe an element, identify it, control its behavior, or provide dynamic values.
For example:
<input
type="text"
id="username"
placeholder="Enter your username"
required
/>
Here:
typedefines the input type.ididentifies the element.placeholderdisplays hint text.requiredmakes the field required.
JSX Attributes vs HTML Attributes
JSX attributes are based on HTML attributes, but JSX has some important differences.
Consider the HTML version:
<div class="card">
<label for="name">Name</label>
</div>
In JSX, you write:
<div className="card">
<label htmlFor="name">Name</label>
</div>
Some attribute names are different because JSX uses JavaScript-style naming conventions and React’s DOM property conventions.
Common examples include:
| HTML | JSX |
|---|---|
class | className |
for | htmlFor |
onclick | onClick |
onchange | onChange |
tabindex | tabIndex |
readonly | readOnly |
maxlength | maxLength |
The important idea is that JSX is not simply HTML written inside JavaScript. JSX has its own syntax and naming rules.
Static Attribute Values
A static attribute has a value that does not change.
For example:
<img
src="/images/logo.png"
alt="Website logo"
/>
The src and alt values are fixed strings.
You can also use attributes such as:
<a href="https://example.com">
Visit Website
</a>
And:
<button title="Save your changes">
Save
</button>
When a value is a normal string, you can use quotation marks.
<p className="description">
Learn React step by step.
</p>
Dynamic Attribute Values
One of the biggest advantages of JSX is that attribute values can come from JavaScript.
Use curly braces {} when the value comes from a JavaScript expression.
const image = "/images/react-logo.png";
<img src={image} alt="React logo" />
Here, image is a JavaScript variable.
React evaluates the expression inside {} and uses the resulting value.
You can also use calculations:
const width = 300;
<img
src="/images/banner.jpg"
alt="Banner"
width={width}
/>
Or a function:
function getTitle() {
return "Learn React";
}
<button title={getTitle()}>
Start Learning
</button>
Strings vs JavaScript Values
Understanding the difference between quoted values and curly braces is extremely important.
A quoted value is treated as a string:
<button title="10">
Button
</button>
A value inside curly braces can be a JavaScript value:
const count = 10;
<button title={count}>
Button
</button>
You can also perform an expression:
const count = 5;
<button title={count + 5}>
Button
</button>
The expression produces 10.
Do not write:
<button title="{count}">
Button
</button>
That passes the literal text {count} rather than evaluating the variable.
The className Attribute
One of the most commonly used JSX attributes is className.
HTML:
<div class="card">
Content
</div>
JSX:
<div className="card">
Content
</div>
You can also make the class dynamic:
const buttonClass = "primary-button";
<button className={buttonClass}>
Submit
</button>
You can build a class value using an expression:
const isActive = true;
<button className={isActive ? "active" : "inactive"}>
Profile
</button>
If isActive is true, the button receives:
active
Otherwise, it receives:
inactive
The id Attribute
The id attribute works in JSX just like it does in HTML.
<h1 id="main-title">
React Tutorial
</h1>
It can also be dynamic:
const sectionId = "react-basics";
<section id={sectionId}>
React Basics
</section>
IDs should generally be unique within the page when they are used as document identifiers.
The title Attribute
The title attribute can provide additional information when the user interacts with an element.
<button title="Save this document">
Save
</button>
It can also be dynamic:
const message = "Save your React project";
<button title={message}>
Save
</button>
Image Attributes
Images commonly use attributes such as src, alt, width, and height.
<img
src="/images/react.png"
alt="React logo"
width={200}
height={200}
/>
Dynamic values are also possible:
const imageUrl = "/images/react.png";
const imageSize = 200;
<img
src={imageUrl}
alt="React logo"
width={imageSize}
height={imageSize}
/>
The alt attribute is particularly important because it provides alternative text for users who cannot see the image and can improve accessibility.
The href Attribute
The href attribute is commonly used with links.
<a href="https://example.com">
Visit Website
</a>
You can make the URL dynamic:
const website = "https://example.com";
<a href={website}>
Visit Website
</a>
You can also create URLs using JavaScript:
const username = "arafat";
<a href={`/profile/${username}`}>
View Profile
</a>
The resulting URL becomes:
/profile/arafat
Boolean Attributes
Some HTML attributes represent an on/off state rather than a value.
Examples include:
disabledrequiredcheckedreadOnlymultipleautoFocus
In JSX, you can write:
<button disabled>
Submit
</button>
This means the button is disabled.
You can also use a JavaScript boolean:
const isDisabled = true;
<button disabled={isDisabled}>
Submit
</button>
If:
const isDisabled = false;
the button is enabled.
This makes boolean attributes particularly useful for dynamic interfaces.
Dynamic Boolean Attributes
Boolean attributes become especially useful when your UI depends on application data.
const isLoggedIn = false;
<button disabled={!isLoggedIn}>
Continue
</button>
If the user is not logged in, the button is disabled.
Another example:
const hasAcceptedTerms = true;
<input
type="checkbox"
checked={hasAcceptedTerms}
/>
The value of checked comes from JavaScript.
In real applications, form controls such as checkboxes and inputs are often controlled through React state.
Event Attributes
JSX also uses attributes for browser events.
Common examples include:
onClick
onChange
onSubmit
onMouseEnter
onMouseLeave
onFocus
onBlur
Notice the capitalization.
For example:
<button onClick={handleClick}>
Click Me
</button>
Here, handleClick is a function.
function handleClick() {
console.log("Button clicked");
}
You should pass the function rather than immediately calling it.
Correct:
<button onClick={handleClick}>
Click
</button>
Usually incorrect:
<button onClick={handleClick()}>
Click
</button>
The second version calls the function while rendering instead of waiting for the click.
You can pass an argument with an arrow function:
<button onClick={() => handleClick("React")}>
Learn React
</button>
Data Attributes
HTML provides data-* attributes for storing custom data.
They can be used in JSX as well.
<button data-course="react">
React Course
</button>
You can also make the value dynamic:
const course = "react";
<button data-course={course}>
React Course
</button>
Other examples include:
<div
data-user-id="101"
data-role="student"
>
Arafat
</div>
These attributes are useful when custom data needs to be associated with a DOM element.
ARIA Attributes
ARIA attributes help make web interfaces more accessible.
Examples include:
<button aria-label="Close menu">
X
</button>
Another example:
<div
role="alert"
aria-live="polite"
>
Your changes have been saved.
</div>
ARIA attributes often use their HTML-style hyphenated names.
For example:
aria-label
aria-hidden
aria-expanded
aria-describedby
Do not convert these into camelCase.
Correct:
<button aria-label="Open menu">
☰
</button>
Dynamic ARIA Attributes
ARIA values can also come from JavaScript.
const isOpen = true;
<button
aria-expanded={isOpen}
aria-label="Toggle navigation"
>
Menu
</button>
The value of aria-expanded changes according to the JavaScript value.
This is particularly useful for menus, dialogs, accordions, tabs, and other interactive components.
JSX Attribute Naming
JSX follows specific naming conventions.
For many DOM properties and event handlers, camelCase is used.
For example:
<button
onClick={handleClick}
onMouseEnter={handleMouseEnter}
>
Button
</button>
Instead of:
<button
onclick={handleClick}
onmouseenter={handleMouseEnter}
>
Button
</button>
Some attributes retain hyphenated names because they are standard HTML or custom data/accessibility attributes.
For example:
<div data-user-id="101">
User
</div>
and:
<button aria-label="Close">
X
</button>
A useful rule is:
Follow React’s DOM attribute naming conventions for standard properties, while data-* and aria-* attributes retain their standard HTML names.
Attributes on React Components
JSX attributes are not limited to HTML elements.
You can also pass attributes to React components.
For example:
function Welcome(props) {
return <h2>Welcome, {props.name}</h2>;
}
You can provide a value when using the component:
<Welcome name="Arafat" />
Here, name is a prop passed to the Welcome component.
The component receives:
props.name
So:
<Welcome name="Arafat" />
is conceptually passing data into the component.
You can pass dynamic values too:
const username = "Arafat";
<Welcome name={username} />
You can pass numbers:
<User age={25} />
Booleans:
<User isAdmin={true} />
Objects:
<User profile={userProfile} />
Arrays:
<User skills={skills} />
Functions:
<User onSelect={handleSelect} />
This is the foundation of React’s props system.
String Props vs JavaScript Props
Consider:
<User name="Arafat" />
This passes the string:
Arafat
But:
<User age={25} />
passes the number:
25
Similarly:
<User isAdmin={true} />
passes a boolean.
And:
<User skills={["HTML", "CSS", "React"]} />
passes an array.
This distinction is important.
String
<User name="Arafat" />
Number
<User age={25} />
Boolean
<User isAdmin={true} />
Array
<User skills={["HTML", "CSS", "React"]} />
Object
<User profile={{ name: "Arafat", age: 25 }} />
Function
<User onSelect={handleSelect} />
Curly braces tell JSX to evaluate the JavaScript expression.
Passing an Object as an Attribute
Objects can be passed through JSX attributes.
const user = {
name: "Arafat",
role: "Developer"
};
<User user={user} />
Inside the component:
function User({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.role}</p>
</div>
);
}
You can also write an object directly:
<User
user={{
name: "Arafat",
role: "Developer"
}}
/>
Notice the two sets of curly braces.
The outer braces mean:
{}
“Evaluate JavaScript.”
The inner braces create the JavaScript object:
{
name: "Arafat",
role: "Developer"
}
Passing Multiple Attributes
A component can receive multiple props.
<User
name="Arafat"
age={25}
role="Developer"
isActive={true}
/>
The component can access them:
function User({ name, age, role, isActive }) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Role: {role}</p>
<p>Status: {isActive ? "Active" : "Inactive"}</p>
</div>
);
}
This is one of the most common patterns you will use when building reusable React components.
Spread Attributes
JSX also supports the spread syntax.
Suppose you have:
const userProps = {
name: "Arafat",
age: 25,
role: "Developer"
};
You can pass all properties to a component using:
<User {...userProps} />
This is equivalent to:
<User
name="Arafat"
age={25}
role="Developer"
/>
Spread syntax can be useful when passing a group of related props.
However, it should be used carefully. Passing every property from a large object can make a component’s interface harder to understand.
Overriding Spread Attributes
The order of attributes matters when using spread syntax.
For example:
const props = {
name: "Arafat",
role: "Student"
};
<User {...props} role="Developer" />
The later role value overrides the value from the spread object.
So the component receives:
name: Arafat
role: Developer
The reverse produces a different result:
<User role="Developer" {...props} />
Now the value from props comes later and can override role.
Therefore, pay attention to the order when using spread attributes.
Conditional Attributes
You can make an attribute depend on a condition.
For example:
const isLoggedIn = true;
<button
disabled={!isLoggedIn}
>
Continue
</button>
You can also dynamically select a class:
const isActive = true;
<div className={isActive ? "active" : "inactive"}>
Dashboard
</div>
Or dynamically choose an image:
const isDarkMode = true;
<img
src={isDarkMode ? "/dark-logo.png" : "/light-logo.png"}
alt="Website logo"
/>
This allows the same JSX structure to respond to changing application data.
Using Expressions in Attributes
Almost any JavaScript expression that produces an appropriate value can be used inside an attribute.
For example:
const firstName = "Arafat";
const lastName = "Khan";
<input
placeholder={`Enter ${firstName}'s name`}
aria-label={`${firstName} ${lastName}`}
/>
You can also use calculations:
const baseWidth = 100;
<img
src="/banner.jpg"
alt="Banner"
width={baseWidth * 2}
/>
You can use logical expressions:
const isDisabled = true;
<button disabled={isDisabled || false}>
Submit
</button>
The expression is evaluated before React applies the resulting value.
Attribute Values Can Be null or undefined
Sometimes you may not want to provide a value.
For example:
const imageUrl = null;
<img
src={imageUrl}
alt="Profile"
/>
React can handle many attributes whose values are null or undefined by treating them as absent.
This is useful for optional attributes.
For example:
const description = undefined;
<div title={description}>
Content
</div>
However, you should still understand the behavior of individual attributes when building more complex interfaces.
Attribute Names Are Case-Sensitive
JSX attribute names must follow the expected spelling.
For example:
<button onClick={handleClick}>
Click
</button>
The capitalization of onClick matters.
Similarly:
<input readOnly />
uses readOnly, not:
<input readonly />
when following React’s standard DOM property naming convention.
Common JSX Attribute Mistakes
Using class Instead of className
Incorrect:
<div class="card">
Hello
</div>
Correct:
<div className="card">
Hello
</div>
Using for Instead of htmlFor
Incorrect:
<label for="email">
Email
</label>
Correct:
<label htmlFor="email">
Email
</label>
Forgetting Curly Braces for Variables
Incorrect:
const imageUrl = "/logo.png";
<img src="imageUrl" alt="Logo" />
This uses the literal string "imageUrl".
Correct:
<img src={imageUrl} alt="Logo" />
Putting JavaScript Expressions in Quotes
Incorrect:
const age = 25;
<User age="{age}" />
Correct:
<User age={age} />
Calling Event Functions During Rendering
Usually incorrect:
<button onClick={handleClick()}>
Click
</button>
Correct:
<button onClick={handleClick}>
Click
</button>
Or, when arguments are required:
<button onClick={() => handleClick("React")}>
Click
</button>
Incorrect Attribute Capitalization
Incorrect:
<button onclick={handleClick}>
Click
</button>
Correct:
<button onClick={handleClick}>
Click
</button>
Forgetting That Component Props Are Data
If you write:
<User name="Arafat" />
the name value does not automatically become a variable inside User.
The component needs to receive it:
function User({ name }) {
return <h2>{name}</h2>;
}
A Practical Example
Let’s combine several JSX attribute concepts into a small React component.
function CourseCard({ course }) {
const isAvailable = course.seats > 0;
return (
<article
className={isAvailable ? "course-card" : "course-card sold-out"}
data-course-id={course.id}
>
<img
src={course.image}
alt={`${course.name} course`}
width={300}
/>
<h2>{course.name}</h2>
<p>{course.description}</p>
<button
disabled={!isAvailable}
aria-label={
isAvailable
? `Enroll in ${course.name}`
: `${course.name} is unavailable`
}
>
{isAvailable ? "Enroll Now" : "Sold Out"}
</button>
</article>
);
}
export default CourseCard;
You could use the component like this:
const course = {
id: 101,
name: "React Fundamentals",
description: "Learn the fundamentals of React.",
image: "/images/react-course.png",
seats: 12
};
<CourseCard course={course} />
This example demonstrates several important concepts:
| Attribute | Purpose |
|---|---|
className | Applies CSS classes |
data-course-id | Stores custom course information |
src | Provides the image source |
alt | Provides alternative image text |
width | Sets the image width |
disabled | Controls button availability |
aria-label | Provides an accessible label |
course | Passes data to a React component |
JSX Attributes Cheat Sheet
| Requirement | JSX Example |
|---|---|
| Static string | title="Hello" |
| Variable | title={pageTitle} |
| Number | width={300} |
| Boolean | disabled={true} |
| Dynamic boolean | disabled={!isValid} |
| Class | className="card" |
| Dynamic class | className={className} |
| Link | href="/about" |
| Image | src={imageUrl} |
| Alternative text | alt="React logo" |
| Event | onClick={handleClick} |
| Data attribute | data-id="101" |
| ARIA attribute | aria-label="Close" |
| Component prop | <User name="Arafat" /> |
| Dynamic prop | <User age={age} /> |
| Spread props | <User {...userProps} /> |
Best Practices for JSX Attributes
Use meaningful values
Prefer:
<img
src="/images/react-course.png"
alt="React course illustration"
/>
instead of:
<img
src="/x.png"
alt="image"
/>
Use dynamic values when data changes
If the value comes from application data, use JavaScript:
<img src={course.image} alt={course.name} />
Follow React naming conventions
Use:
className
htmlFor
onClick
onChange
readOnly
tabIndex
Keep component props understandable
Prefer:
<User
name={name}
role={role}
isActive={isActive}
/>
over passing a huge object when only a few values are needed.
Use accessibility attributes where appropriate
For interactive elements, meaningful labels and states are important.
<button aria-label="Close dialog">
×
</button>
Practice Exercise
Create a ProductCard component.
The component should receive:
product
The product object should contain:
const product = {
id: 1,
name: "React Course",
image: "/react-course.png",
price: 999,
available: true
};
Your component should:
- Display the product image.
- Use the product name as the image
alt. - Display the product name.
- Display the price.
- Disable the button when the product is unavailable.
- Use a dynamic
className. - Add a
data-product-idattribute. - Add an appropriate
aria-labelto the button.
Try creating it yourself before looking for a solution.
Where to Place an Image
Place this image after the section “Dynamic Attribute Values” and before “The className Attribute”.
The image should visually show the difference between a static JSX attribute and a dynamic JSX attribute:
Static
<img src="/logo.png" />
VS
Dynamic
const imageUrl = "/logo.png";
<img src={imageUrl} />
Use a clean 16:9 React developer infographic with JSX code, curly braces highlighted, and a modern dark coding-editor aesthetic.
Caption: Static and dynamic attribute values in JSX
Alt text: Static and dynamic JSX attributes using quoted strings and JavaScript expressions
Key Takeaways
- JSX attributes provide additional information to HTML elements and React components.
- Static string values can be written inside quotation marks.
- JavaScript values and expressions are written inside
{}. - JSX uses React’s naming conventions for many DOM attributes.
- Use
classNameinstead ofclass. - Use
htmlForinstead offor. - Event handlers use names such as
onClickandonChange. - Boolean attributes can receive JavaScript boolean values.
data-*andaria-*attributes can be used in JSX.- Attributes on React components are commonly called props.
- Props can contain strings, numbers, booleans, arrays, objects, and functions.
- Spread syntax can pass multiple props at once.
- Dynamic attributes allow your interface to respond to application data.
- Good attribute usage improves maintainability, accessibility, and component reusability.
Once you understand JSX attributes, you can start building components that are not just static UI elements, but interfaces that respond to real application data.