0
# Thresholds
1
2
Pre-defined threshold constants for determining metric ratings according to Web Vitals standards. These thresholds classify metric values as "good", "needs improvement", or "poor" based on real-world performance data and user experience research.
3
4
## Capabilities
5
6
### Threshold Constants
7
8
Each Web Vitals metric has associated threshold constants that define the boundaries between performance ratings.
9
10
```typescript { .api }
11
/**
12
* CLS thresholds: [0.1, 0.25]
13
* - ≤ 0.1: good
14
* - 0.1 - 0.25: needs improvement
15
* - > 0.25: poor
16
*/
17
const CLSThresholds: MetricRatingThresholds;
18
19
/**
20
* FCP thresholds: [1800, 3000] (milliseconds)
21
* - ≤ 1800ms: good
22
* - 1800ms - 3000ms: needs improvement
23
* - > 3000ms: poor
24
*/
25
const FCPThresholds: MetricRatingThresholds;
26
27
/**
28
* INP thresholds: [200, 500] (milliseconds)
29
* - ≤ 200ms: good
30
* - 200ms - 500ms: needs improvement
31
* - > 500ms: poor
32
*/
33
const INPThresholds: MetricRatingThresholds;
34
35
/**
36
* LCP thresholds: [2500, 4000] (milliseconds)
37
* - ≤ 2500ms: good
38
* - 2500ms - 4000ms: needs improvement
39
* - > 4000ms: poor
40
*/
41
const LCPThresholds: MetricRatingThresholds;
42
43
/**
44
* TTFB thresholds: [800, 1800] (milliseconds)
45
* - ≤ 800ms: good
46
* - 800ms - 1800ms: needs improvement
47
* - > 1800ms: poor
48
*/
49
const TTFBThresholds: MetricRatingThresholds;
50
51
type MetricRatingThresholds = [number, number];
52
```
53
54
## Usage Examples
55
56
### Import and Use Thresholds
57
58
```typescript
59
import {
60
CLSThresholds,
61
FCPThresholds,
62
INPThresholds,
63
LCPThresholds,
64
TTFBThresholds
65
} from "web-vitals";
66
67
// Check threshold values
68
console.log('CLS thresholds:', CLSThresholds); // [0.1, 0.25]
69
console.log('FCP thresholds:', FCPThresholds); // [1800, 3000]
70
console.log('INP thresholds:', INPThresholds); // [200, 500]
71
console.log('LCP thresholds:', LCPThresholds); // [2500, 4000]
72
console.log('TTFB thresholds:', TTFBThresholds); // [800, 1800]
73
```
74
75
### Manual Rating Calculation
76
77
Although the `Metric.rating` property automatically provides ratings, you can manually calculate ratings using the thresholds:
78
79
```typescript
80
import { LCPThresholds } from "web-vitals";
81
82
function calculateRating(value: number, thresholds: MetricRatingThresholds): string {
83
if (value <= thresholds[0]) {
84
return 'good';
85
} else if (value <= thresholds[1]) {
86
return 'needs-improvement';
87
} else {
88
return 'poor';
89
}
90
}
91
92
// Example usage
93
const lcpValue = 3200; // 3.2 seconds
94
const rating = calculateRating(lcpValue, LCPThresholds);
95
console.log('LCP rating:', rating); // 'needs-improvement'
96
```
97
98
### Custom Threshold Analysis
99
100
```typescript
101
import { onLCP, LCPThresholds } from "web-vitals";
102
103
onLCP((metric) => {
104
const [goodThreshold, poorThreshold] = LCPThresholds;
105
106
console.log(`LCP: ${metric.value}ms (${metric.rating})`);
107
108
if (metric.rating === 'poor') {
109
const improvement = metric.value - poorThreshold;
110
console.log(`Need to improve by ${improvement}ms to reach 'needs-improvement'`);
111
} else if (metric.rating === 'needs-improvement') {
112
const improvement = metric.value - goodThreshold;
113
console.log(`Need to improve by ${improvement}ms to reach 'good'`);
114
}
115
});
116
```
117
118
### Threshold-Based Monitoring
119
120
```typescript
121
import {
122
onCLS, onFCP, onINP, onLCP, onTTFB,
123
CLSThresholds, FCPThresholds, INPThresholds, LCPThresholds, TTFBThresholds
124
} from "web-vitals";
125
126
// Monitor metrics and alert on poor performance
127
const thresholds = {
128
CLS: CLSThresholds,
129
FCP: FCPThresholds,
130
INP: INPThresholds,
131
LCP: LCPThresholds,
132
TTFB: TTFBThresholds
133
};
134
135
function monitorMetric(metricName: string, metric: any) {
136
const threshold = thresholds[metricName as keyof typeof thresholds];
137
138
if (metric.rating === 'poor') {
139
console.warn(`⚠️ Poor ${metricName}: ${metric.value} (threshold: >${threshold[1]})`);
140
141
// Send alert to monitoring system
142
sendAlert({
143
metric: metricName,
144
value: metric.value,
145
rating: metric.rating,
146
threshold: threshold[1]
147
});
148
}
149
}
150
151
// Set up monitoring
152
onCLS(metric => monitorMetric('CLS', metric));
153
onFCP(metric => monitorMetric('FCP', metric));
154
onINP(metric => monitorMetric('INP', metric));
155
onLCP(metric => monitorMetric('LCP', metric));
156
onTTFB(metric => monitorMetric('TTFB', metric));
157
```
158
159
## Rating System Details
160
161
### Rating Categories
162
163
Each metric value falls into one of three categories:
164
165
- **Good**: Represents a great user experience
166
- **Needs Improvement**: Indicates room for optimization
167
- **Poor**: Suggests significant performance issues
168
169
### Threshold Methodology
170
171
The threshold values are based on:
172
173
1. **Real-world data** from Chrome User Experience Report (CrUX)
174
2. **User experience research** correlating performance with user satisfaction
175
3. **75th percentile** targets for good performance
176
4. **Statistical analysis** of millions of web pages
177
178
### Metric-Specific Considerations
179
180
#### CLS (Cumulative Layout Shift)
181
- **Unit**: Unitless score (0 = no shifts, higher = more shifts)
182
- **Good**: ≤ 0.1 (minimal unexpected layout shifts)
183
- **Poor**: > 0.25 (significant visual instability)
184
185
#### FCP (First Contentful Paint)
186
- **Unit**: Milliseconds from navigation start
187
- **Good**: ≤ 1.8s (fast content appearance)
188
- **Poor**: > 3s (slow content appearance)
189
190
#### INP (Interaction to Next Paint)
191
- **Unit**: Milliseconds of interaction latency
192
- **Good**: ≤ 200ms (imperceptible delay)
193
- **Poor**: > 500ms (noticeable delay)
194
195
#### LCP (Largest Contentful Paint)
196
- **Unit**: Milliseconds from navigation start
197
- **Good**: ≤ 2.5s (fast loading of main content)
198
- **Poor**: > 4s (slow loading of main content)
199
200
#### TTFB (Time to First Byte)
201
- **Unit**: Milliseconds from navigation start
202
- **Good**: ≤ 800ms (fast server response)
203
- **Poor**: > 1.8s (slow server response)
204
205
## Important Notes
206
207
### Automatic Rating
208
209
The Web Vitals library automatically calculates and provides the rating in the `metric.rating` property, so manual threshold checking is typically unnecessary:
210
211
```typescript
212
import { onLCP } from "web-vitals";
213
214
onLCP((metric) => {
215
// Rating is automatically calculated
216
console.log('LCP rating:', metric.rating); // 'good', 'needs-improvement', or 'poor'
217
218
// No need to manually check thresholds
219
// const rating = metric.value <= LCPThresholds[0] ? 'good' :
220
// metric.value <= LCPThresholds[1] ? 'needs-improvement' : 'poor';
221
});
222
```
223
224
### Threshold Updates
225
226
Threshold values may be updated in future versions of the library to reflect evolving web performance standards and user expectations. Always use the exported constants rather than hardcoding values.
227
228
### Cross-Metric Analysis
229
230
```typescript
231
import { onLCP, onCLS, onINP } from "web-vitals";
232
233
const metrics = {
234
lcp: null as any,
235
cls: null as any,
236
inp: null as any
237
};
238
239
onLCP(metric => metrics.lcp = metric);
240
onCLS(metric => metrics.cls = metric);
241
onINP(metric => metrics.inp = metric);
242
243
// Analyze overall page performance
244
setTimeout(() => {
245
const goodMetrics = Object.values(metrics)
246
.filter(metric => metric && metric.rating === 'good').length;
247
248
const totalMetrics = Object.values(metrics)
249
.filter(metric => metric !== null).length;
250
251
console.log(`Overall performance: ${goodMetrics}/${totalMetrics} metrics are good`);
252
}, 5000);
253
```