or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

babel-macro.mdbuild-integration.mdcomponent-styling.mdexternal-css.mdindex.mdstyle-registry.md

component-styling.mddocs/

0

# Component Styling

1

2

Core CSS-in-JS functionality for writing scoped styles directly in JSX components with full CSS support and automatic scoping.

3

4

## Capabilities

5

6

### Basic Scoped Styles

7

8

The fundamental way to add CSS to React components. Styles are automatically scoped to the component using unique class names.

9

10

```jsx { .api }

11

<style jsx>{`/* CSS rules */`}</style>

12

```

13

14

**Usage Example:**

15

16

```jsx

17

function Card({ title, children }) {

18

return (

19

<div className="card">

20

<h2>{title}</h2>

21

<div className="content">{children}</div>

22

<style jsx>{`

23

.card {

24

border: 1px solid #ddd;

25

border-radius: 8px;

26

padding: 16px;

27

margin: 8px;

28

background: white;

29

box-shadow: 0 2px 4px rgba(0,0,0,0.1);

30

}

31

.content {

32

margin-top: 12px;

33

line-height: 1.5;

34

}

35

h2 {

36

margin: 0;

37

color: #333;

38

font-size: 1.2em;

39

}

40

`}</style>

41

</div>

42

);

43

}

44

```

45

46

### Global Styles

47

48

Apply styles globally across the entire application, bypassing component scoping.

49

50

```jsx { .api }

51

<style jsx global>{`/* Global CSS rules */`}</style>

52

```

53

54

**Usage Example:**

55

56

```jsx

57

function App() {

58

return (

59

<div>

60

<h1>My App</h1>

61

<style jsx global>{`

62

body {

63

margin: 0;

64

padding: 0;

65

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

66

background: #f5f5f5;

67

}

68

* {

69

box-sizing: border-box;

70

}

71

h1, h2, h3 {

72

color: #2c3e50;

73

}

74

`}</style>

75

</div>

76

);

77

}

78

```

79

80

### Dynamic Styles

81

82

Use JavaScript expressions within CSS for props-based styling and conditional styles.

83

84

```jsx { .api }

85

<style jsx>{`

86

.element {

87

property: ${expression};

88

}

89

`}</style>

90

```

91

92

**Usage Examples:**

93

94

```jsx

95

// Props-based styling

96

function Button({ size = 'medium', variant = 'primary', disabled, children }) {

97

const sizes = {

98

small: { padding: '8px 16px', fontSize: '14px' },

99

medium: { padding: '12px 24px', fontSize: '16px' },

100

large: { padding: '16px 32px', fontSize: '18px' }

101

};

102

103

const variants = {

104

primary: { background: '#007bff', color: 'white' },

105

secondary: { background: '#6c757d', color: 'white' },

106

outline: { background: 'transparent', color: '#007bff', border: '1px solid #007bff' }

107

};

108

109

return (

110

<button disabled={disabled}>

111

{children}

112

<style jsx>{`

113

button {

114

padding: ${sizes[size].padding};

115

font-size: ${sizes[size].fontSize};

116

background: ${disabled ? '#e9ecef' : variants[variant].background};

117

color: ${disabled ? '#6c757d' : variants[variant].color};

118

border: ${variants[variant].border || 'none'};

119

border-radius: 4px;

120

cursor: ${disabled ? 'not-allowed' : 'pointer'};

121

transition: all 0.2s ease;

122

}

123

button:hover {

124

opacity: ${disabled ? '1' : '0.9'};

125

transform: ${disabled ? 'none' : 'translateY(-1px)'};

126

}

127

`}</style>

128

</button>

129

);

130

}

131

132

// State-based styling

133

function Toggle({ isOn, onToggle }) {

134

return (

135

<div className="toggle" onClick={onToggle}>

136

<div className="slider" />

137

<style jsx>{`

138

.toggle {

139

width: 60px;

140

height: 30px;

141

background: ${isOn ? '#4CAF50' : '#ccc'};

142

border-radius: 15px;

143

position: relative;

144

cursor: pointer;

145

transition: background 0.3s;

146

}

147

.slider {

148

width: 26px;

149

height: 26px;

150

background: white;

151

border-radius: 50%;

152

position: absolute;

153

top: 2px;

154

left: ${isOn ? '32px' : '2px'};

155

transition: left 0.3s;

156

box-shadow: 0 2px 4px rgba(0,0,0,0.2);

157

}

158

`}</style>

159

</div>

160

);

161

}

162

```

163

164

### Targeting Root Element

165

166

Target the component's root element using class names, similar to CSS-in-JS :host selector.

167

168

```jsx { .api }

169

// Root element gets jsx-* class automatically

170

<div className="root">

171

<style jsx>{`

172

.root {

173

/* styles for root element */

174

}

175

`}</style>

176

</div>

177

```

178

179

**Usage Example:**

180

181

```jsx

182

function Modal({ isOpen, onClose, children }) {

183

if (!isOpen) return null;

184

185

return (

186

<div className="modal-overlay">

187

<div className="modal">

188

<button className="close" onClick={onClose}>×</button>

189

{children}

190

<style jsx>{`

191

.modal-overlay {

192

position: fixed;

193

top: 0;

194

left: 0;

195

right: 0;

196

bottom: 0;

197

background: rgba(0, 0, 0, 0.5);

198

display: flex;

199

align-items: center;

200

justify-content: center;

201

z-index: 1000;

202

}

203

.modal {

204

background: white;

205

border-radius: 8px;

206

padding: 24px;

207

max-width: 500px;

208

max-height: 80vh;

209

overflow-y: auto;

210

position: relative;

211

}

212

.close {

213

position: absolute;

214

top: 8px;

215

right: 12px;

216

background: none;

217

border: none;

218

font-size: 24px;

219

cursor: pointer;

220

color: #999;

221

}

222

.close:hover {

223

color: #333;

224

}

225

`}</style>

226

</div>

227

</div>

228

);

229

}

230

```

231

232

### One-off Global Selectors

233

234

Use `:global()` pseudo-selector to target elements without scoping, useful for styling third-party components.

235

236

```jsx { .api }

237

<style jsx>{`

238

:global(.third-party-class) {

239

/* unscoped styles */

240

}

241

.local-class :global(.nested-global) {

242

/* mixed scoped and global */

243

}

244

`}</style>

245

```

246

247

**Usage Example:**

248

249

```jsx

250

import Select from 'react-select';

251

252

function CustomSelect({ options, value, onChange }) {

253

return (

254

<div className="select-container">

255

<Select

256

options={options}

257

value={value}

258

onChange={onChange}

259

className="react-select"

260

classNamePrefix="react-select"

261

/>

262

<style jsx>{`

263

.select-container {

264

margin: 16px 0;

265

}

266

267

/* Style react-select components globally */

268

.select-container :global(.react-select__control) {

269

border: 2px solid #e1e5e9;

270

border-radius: 8px;

271

min-height: 44px;

272

box-shadow: none;

273

}

274

275

.select-container :global(.react-select__control--is-focused) {

276

border-color: #007bff;

277

box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);

278

}

279

280

.select-container :global(.react-select__option--is-focused) {

281

background-color: #f8f9fa;

282

}

283

284

.select-container :global(.react-select__option--is-selected) {

285

background-color: #007bff;

286

}

287

`}</style>

288

</div>

289

);

290

}

291

```

292

293

### Constants and External Values

294

295

Use constants defined outside component scope for consistent theming and reusable values.

296

297

```jsx { .api }

298

// Constants are treated as static styles (no re-computation)

299

const theme = { primary: '#007bff', spacing: '16px' };

300

301

<style jsx>{`

302

.element {

303

color: ${theme.primary};

304

margin: ${theme.spacing};

305

}

306

`}</style>

307

```

308

309

**Usage Example:**

310

311

```jsx

312

// theme.js

313

export const theme = {

314

colors: {

315

primary: '#007bff',

316

secondary: '#6c757d',

317

success: '#28a745',

318

danger: '#dc3545',

319

warning: '#ffc107',

320

info: '#17a2b8',

321

light: '#f8f9fa',

322

dark: '#343a40'

323

},

324

spacing: {

325

xs: '4px',

326

sm: '8px',

327

md: '16px',

328

lg: '24px',

329

xl: '32px'

330

},

331

breakpoints: {

332

sm: '576px',

333

md: '768px',

334

lg: '992px',

335

xl: '1200px'

336

}

337

};

338

339

// Component using theme constants

340

import { theme } from './theme';

341

342

function Alert({ type = 'info', children }) {

343

return (

344

<div className={`alert alert-${type}`}>

345

{children}

346

<style jsx>{`

347

.alert {

348

padding: ${theme.spacing.md};

349

margin: ${theme.spacing.sm} 0;

350

border: 1px solid transparent;

351

border-radius: 4px;

352

}

353

.alert-primary {

354

background-color: ${theme.colors.primary}15;

355

border-color: ${theme.colors.primary}30;

356

color: ${theme.colors.primary};

357

}

358

.alert-success {

359

background-color: ${theme.colors.success}15;

360

border-color: ${theme.colors.success}30;

361

color: ${theme.colors.success};

362

}

363

.alert-danger {

364

background-color: ${theme.colors.danger}15;

365

border-color: ${theme.colors.danger}30;

366

color: ${theme.colors.danger};

367

}

368

@media (max-width: ${theme.breakpoints.md}) {

369

.alert {

370

padding: ${theme.spacing.sm};

371

margin: ${theme.spacing.xs} 0;

372

}

373

}

374

`}</style>

375

</div>

376

);

377

}

378

```