Web page title blinking: setInterval(() => document.title = document.title === 'Slacking off' ? '🐟' : 'Slacking off', 500);
Flashing Web Page Title: setInterval(() => document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off', 500);
A flashing web page title is a common dynamic effect that can be easily achieved using JavaScript's setInterval
function. This code switches the document title between "Slacking Off" and "🐟" at 500-millisecond intervals, creating a visual flashing effect.
Implementation Principle Analysis
The core of this code is the combination of the setInterval
function and a ternary operator:
setInterval(() => {
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
setInterval
takes two parameters: a callback function and a time interval (in milliseconds). Here, the interval is set to 500 milliseconds, meaning the callback function executes every half second.
The callback function uses a ternary operator to check the current title:
- If the current title is "Slacking Off," it changes to "🐟"
- If not (i.e., it's already "🐟"), it reverts to "Slacking Off"
Extended Application Scenarios
This technique can be applied to various scenarios:
- Notification Alerts: Flash the title when new messages arrive
let originalTitle = document.title;
let hasNewMessage = false;
function toggleNotification() {
document.title = hasNewMessage ?
'【New Message】' + originalTitle :
originalTitle;
hasNewMessage = !hasNewMessage;
}
const notificationInterval = setInterval(toggleNotification, 1000);
// When a new message is received
function onNewMessage() {
hasNewMessage = true;
clearInterval(notificationInterval);
notificationInterval = setInterval(toggleNotification, 1000);
}
- Countdown Effect:
let seconds = 10;
const countdown = setInterval(() => {
document.title = `Time Left: ${seconds}s`;
seconds--;
if(seconds < 0) {
clearInterval(countdown);
document.title = "Time's Up!";
}
}, 1000);
Performance Optimization Considerations
While this effect is cool, performance issues should be noted:
- Clearing Timers: Ensure timers are cleared when not needed
let blinkInterval;
function startBlinking() {
blinkInterval = setInterval(() => {
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
}
function stopBlinking() {
clearInterval(blinkInterval);
document.title = 'Slacking Off';
}
- Using requestAnimationFrame as an Alternative: For smoother animations
let lastTime = 0;
const interval = 500;
function blinkTitle(timestamp) {
if(timestamp - lastTime > interval) {
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
lastTime = timestamp;
}
requestAnimationFrame(blinkTitle);
}
requestAnimationFrame(blinkTitle);
Browser Compatibility
While modern browsers support this technique, note:
- Mobile Browsers: Some may limit title update frequency
- SEO Impact: Frequent title changes may harm search engine optimization
- User Experience: Overuse may distract users
Advanced Techniques
- Multi-State Flashing:
const states = ['Working', 'Break', 'Coffee Time'];
let index = 0;
setInterval(() => {
document.title = states[index];
index = (index + 1) % states.length;
}, 1000);
- Random Effects:
const emojis = ['🐟', '🎣', '🏖️', '🛏️', '📱'];
setInterval(() => {
document.title = emojis[Math.floor(Math.random() * emojis.length)];
}, 300);
- Combining with Page Visibility API:
let intervalId;
function handleVisibilityChange() {
if (document.hidden) {
intervalId = setInterval(() => {
document.title = document.title === 'Come Back!' ? 'Page in Background' : 'Come Back!';
}, 500);
} else {
clearInterval(intervalId);
document.title = 'Welcome Back';
}
}
document.addEventListener('visibilitychange', handleVisibilityChange);
Practical Application Examples
- Chat Applications: When receiving new messages
let isBlinking = false;
let originalTitle = document.title;
socket.on('new-message', () => {
if(!isBlinking) {
isBlinking = true;
const blinkInterval = setInterval(() => {
document.title = document.title === originalTitle ?
'New Message!' :
originalTitle;
}, 800);
// Stop flashing when user returns to the tab
window.addEventListener('focus', function stopBlink() {
clearInterval(blinkInterval);
document.title = originalTitle;
isBlinking = false;
window.removeEventListener('focus', stopBlink);
});
}
});
- Game Applications: When player health is low
let playerHealth = 100;
function updateHealth(change) {
playerHealth += change;
if(playerHealth < 30 && playerHealth > 0) {
// Start flashing warning
if(!window.healthWarningInterval) {
window.healthWarningInterval = setInterval(() => {
document.title = document.title.includes('⚠️') ?
'Low Health!' :
'⚠️ Low Health! ⚠️';
}, 600);
}
} else if(playerHealth <= 0) {
clearInterval(window.healthWarningInterval);
document.title = 'Game Over';
} else {
clearInterval(window.healthWarningInterval);
window.healthWarningInterval = null;
document.title = 'Adventure Game';
}
}
User Experience Considerations
While title flashing can attract attention, consider:
- Flash Frequency: Too fast may cause discomfort; recommend at least 500ms
- Duration: Prolonged flashing may annoy; set auto-stop
- User Control: Provide options to disable flashing
// Add a stop button on the page
document.getElementById('stopBlink').addEventListener('click', () => {
clearInterval(blinkInterval);
document.title = 'Slacking Off';
});
- Accessibility: Ensure it doesn't disturb screen reader users
Integration with Other APIs
- Combining with Notification API:
// Request notification permission first
Notification.requestPermission().then(permission => {
if(permission === 'granted') {
setInterval(() => {
if(document.hidden) {
document.title = document.title === 'New Notification' ? 'Please Check' : 'New Notification';
new Notification('You have a new message', {
body: 'Please return to the tab',
icon: '/notification-icon.png'
});
}
}, 10000);
}
});
- Combining with WebSocket:
const socket = new WebSocket('wss://example.com/ws');
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
if(data.urgent) {
let counter = 0;
const urgentInterval = setInterval(() => {
document.title = `【Urgent】${data.message.slice(0, 10)}...`;
if(++counter >= 10) {
clearInterval(urgentInterval);
document.title = 'Normal Title';
}
}, 500);
}
};
Debugging Tips
When title flashing doesn't work, debug like this:
- Check if Timer is Set Successfully:
const intervalId = setInterval(() => {
console.log('Executing interval callback'); // Confirm if callback executes
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
// In console, try clearInterval(intervalId) to stop
- Verify Title Modification Permissions:
try {
document.title = 'Test Title';
console.log('Title modified successfully');
} catch(e) {
console.error('Title modification failed:', e);
}
- Performance Monitoring:
const start = performance.now();
let count = 0;
const interval = setInterval(() => {
document.title = `Count: ${++count}`;
if(count >= 10) {
clearInterval(interval);
const duration = performance.now() - start;
console.log(`10 updates took: ${duration}ms`);
}
}, 100);
Alternative Solutions
Beyond setInterval
, other implementations exist:
- Using CSS Animation and MutationObserver:
<style>
@keyframes titleBlink {
0%, 100% { content: "Slacking Off"; }
50% { content: "🐟"; }
}
</style>
<script>
const observer = new MutationObserver(() => {
document.title = getComputedStyle(document.documentElement, '::before')
.getPropertyValue('content')
.replace(/["']/g, '');
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['style']
});
document.documentElement.style.setProperty('--title-content', '"Slacking Off"');
document.documentElement.style.animation = 'titleBlink 1s infinite';
</script>
- Using Web Worker:
// worker.js
let toggle = false;
setInterval(() => {
self.postMessage(toggle ? 'Slacking Off' : '🐟');
toggle = !toggle;
}, 500);
// Main thread
const worker = new Worker('worker.js');
worker.onmessage = (e) => {
document.title = e.data;
};
Security Considerations
- Prevent XSS Attacks: Ensure dynamic title content is escaped
function setSafeTitle(text) {
const div = document.createElement('div');
div.textContent = text;
document.title = div.innerHTML;
}
setInterval(() => {
setSafeTitle(document.title === 'Safe' ? '<script>alert(1)</script>' : 'Safe');
}, 1000);
- Avoid Sensitive Information: Don't expose private data in titles
- Permission Control: Some browser extensions may limit title modifications
History and Development
The history of dynamic web title modification dates back to early JavaScript:
- Early Implementation: Supported since Netscape Navigator era
- Browser Wars: Different browsers had varying frequency limits
- Modern Standards: HTML5 specifications clarified title modification behavior
Cross-Platform Behavior Differences
Title flashing behaves differently across environments:
- Desktop Browsers: Generally consistent
- Mobile Browsers: May be throttled or ignored
- PWA Apps: Behavior may differ when running as standalone windows
- Electron Apps: Offers more control freedom
Implementation in Frameworks
Implementation in popular frameworks:
- React:
import { useEffect, useState } from 'react';
function BlinkingTitle() {
const [title, setTitle] = useState('Slacking Off');
useEffect(() => {
const interval = setInterval(() => {
setTitle(prev => prev === 'Slacking Off' ? '🐟' : 'Slacking Off');
}, 500);
return () => clearInterval(interval);
}, []);
useEffect(() => {
document.title = title;
}, [title]);
return null;
}
- Vue:
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const title = ref('Slacking Off');
onMounted(() => {
const interval = setInterval(() => {
title.value = title.value === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
onUnmounted(() => clearInterval(interval));
});
watch(title, (newVal) => {
document.title = newVal;
});
</script>
- Angular:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Title } from '@angular/platform-browser';
@Component({
selector: 'app-blink-title',
template: ''
})
export class BlinkTitleComponent implements OnInit, OnDestroy {
private interval: any;
constructor(private titleService: Title) {}
ngOnInit() {
let isFish = true;
this.interval = setInterval(() => {
isFish = !isFish;
this.titleService.setTitle(isFish ? 'Slacking Off' : '🐟');
}, 500);
}
ngOnDestroy() {
clearInterval(this.interval);
}
}
Testing Strategies
How to test title flashing functionality:
- Unit Testing (using Jest):
// Mock document.title
let mockTitle = '';
Object.defineProperty(document, 'title', {
get: () => mockTitle,
set: (value) => { mockTitle = value; }
});
test('Title should alternate', () => {
jest.useFakeTimers();
const interval = setInterval(() => {
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
expect(document.title).toBe('');
jest.advanceTimersByTime(500);
expect(document.title).toBe('Slacking Off');
jest.advanceTimersByTime(500);
expect(document.title).toBe('🐟');
jest.advanceTimersByTime(500);
expect(document.title).toBe('Slacking Off');
clearInterval(interval);
});
- E2E Testing (using Cypress):
describe('Title Flashing', () => {
it('should change every 500ms', () => {
cy.visit('/');
cy.title().should('eq', 'Slacking Off');
cy.wait(500);
cy.title().should('eq', '🐟');
cy.wait(500);
cy.title().should('eq', 'Slacking Off');
});
});
Performance Impact Measurement
Measuring the performance impact of title updates:
const iterations = 1000;
let totalTime = 0;
function testTitleUpdate() {
const start = performance.now();
for(let i = 0; i < iterations; i++) {
document.title = `Test ${i}`;
}
const duration = performance.now() - start;
totalTime += duration;
console.log(`Completed ${iterations} title updates in: ${duration}ms`);
if(totalTime < 1000) {
requestAnimationFrame(testTitleUpdate);
} else {
console.log(`Average title update time: ${totalTime/iterations}ms`);
}
}
testTitleUpdate();
Browser Limitations and Countermeasures
Browser-specific limitations on title modifications:
- Frequency Limits: Some browsers restrict modification frequency
- Background Tabs: Inactive tabs may be throttled
- Countermeasures:
let lastUpdate = 0;
const minInterval = 300; // Minimum 300ms interval
function safeTitleUpdate(newTitle) {
const now = performance.now();
if(now - lastUpdate >= minInterval) {
document.title = newTitle;
lastUpdate = now;
return true;
}
return false;
}
// Usage
setInterval(() => {
safeTitleUpdate(document.title === 'Slacking Off' ? '🐟' : 'Slacking Off');
}, 100); // Attempt 100ms interval, but will be limited
User Experience Research
Impact of title flashing on user experience:
- Attention Grabbing: Effective but potentially excessive
- Anxiety: Frequent flashing may cause stress
- Best Practices:
- Use only for important notifications
- Provide obvious disable options
- Combine with visual cues (e.g., favicon changes)
Accessibility Improvements
Ensure title flashing doesn't hinder accessibility:
- Screen Readers: Frequent changes may interfere
- Improved Solution:
let isScreenReader = false;
// Detect screen readers (imperfect but helpful)
if(window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
isScreenReader = true;
}
function accessibleTitleBlink() {
if(isScreenReader) {
document.title = 'New Notification';
return;
}
// Normal flashing logic
setInterval(() => {
document.title = document.title === 'Slacking Off' ? '🐟' : 'Slacking Off';
}, 500);
}
Creative Application Examples
Some interesting creative implementations:
- Progress Animation:
const frames = ['-', '\\', '|', '/'];
let index = 0;
setInterval(() => {
document.title = `Processing ${frames[index]}`;
index = (index + 1) % frames.length;
}, 100);
- Typewriter Effect:
const text = "New message incoming...";
let position = 0;
let adding = true;
setInterval(() => {
if(adding) {
document.title = text.slice(0, position++);
if(position > text.length) {
adding = false;
setTimeout(() => {}, 1000);
}
} else {
document.title = text.slice(0, position--);
if(position < 0) {
adding = true;
}
}
}, 100);
- Color Code Flashing (partial browser support):
const colors = ['red', 'blue', 'green', 'yellow'];
let colorIndex = 0;
setInterval(() => {
document.title = `%c${colors[colorIndex]}Title`;
colorIndex = (colorIndex + 1) % colors.length;
}, 500);
Combining with Other DOM Properties
Not limited to titles; can combine with other properties:
- Favicon Flashing:
const canvas = document.createElement('canvas');
canvas.width = 16; canvas.height = 16;
const ctx = canvas.getContext('2d');
let isYellow = false;
setInterval(() => {
isYellow = !isYellow;
ctx.fillStyle = isYellow ? 'yellow' : 'red';
ctx.fillRect(0, 0, 16, 16);
const link = document.querySelector("link[rel*='icon']") ||
document.createElement('link');
link.type = 'image/x-icon';
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn