colortag.js is a lightweight JavaScript library for adding color-coded tagging functionality to HTML elements. It provides an intuitive, touch-friendly interface for applying and removing color tags, inspired by macOS Finder's tagging system.
- 🎨 Color-coded tags with customizable palette
- 📱 Touch-friendly interface with desktop hover effects
- ⌨️ Full keyboard navigation support for accessibility
- 🔄 Simple API with event hooks for integration
- 🏷️ Support for initial tags via data attributes
- 🎯 Flexible element targeting with CSS selectors
- 📊 Automatic tag container creation
- 🔎 Named colors for better semantics
- 💻 Clean, modern SVG-based UI
- 📝 No dependencies, lightweight codebase
- 🔄 Change colors at initialization time
- Download the repository files
- Include the CSS and JS files in your project:
<link rel="stylesheet" href="css/style.css">
<script src="js/colortag.js"></script>- Add HTML elements with the class
taggable-itemcontaining a div with classitem-tags:
<div class="taggable-item" id="my-item">
<p>My taggable content</p>
<div class="item-tags"></div>
</div>- Initialize the ColorTag library:
document.addEventListener('DOMContentLoaded', () => {
const colorTag = new ColorTag();
colorTag.init();
});You can provide custom colors in two ways:
const colorTag = new ColorTag({
colors: [
{ name: 'Ruby', color: '#FF0000' },
{ name: 'Emerald', color: '#00FF00' },
{ name: 'Sapphire', color: '#0000FF' },
{ name: 'Gold', color: '#FFFF00' }
]
});You can also provide just hex values, and names will be generated automatically:
const colorTag = new ColorTag({
colors: ['#FF0000', '#00FF00', '#0000FF', '#FFFF00']
});You can also pass objects that only define a color property. In that case the
library will generate a name automatically:
const colorTag = new ColorTag({
colors: [
{ color: '#FF0000' },
{ color: '#00FF00' },
{ color: '#0000FF' }
]
});You can pass colors directly to the init() method as a second parameter:
const colorTag = new ColorTag();
colorTag.init('.document-items', [
{ name: 'Important', color: '#FF0000' },
{ name: 'Review', color: '#FFFF00' },
{ name: 'Approved', color: '#00FF00' }
]);Or you can pass an options object to init():
const colorTag = new ColorTag();
colorTag.init({
selector: '.document-items',
colors: ['#FF0000', '#00FF00', '#0000FF']
});This approach is useful when:
- You need different color sets for different groups of elements
- Colors need to be loaded dynamically from a server
- You want to change colors based on user preferences
You can customize the CSS class names used by the library:
const colorTag = new ColorTag({
taggableItemClass: 'my-taggable-item',
itemTagsClass: 'my-item-tags'
});You can initialize only specific elements by providing a CSS selector to the init() method:
// Initialize by class
colorTag.init('.content-items .document');
// Initialize by ID
colorTag.init('#specific-document');
// Initialize with complex selector
colorTag.init('.dashboard article[data-type="file"]');When initializing with a selector, ColorTag will:
- Add the
taggableItemClassto the elements if they don't have it - Create a tag container if one doesn't exist
- Setup all the necessary event listeners
You can specify initial tags using the data-initial-tags attribute:
<!-- Using color names -->
<div class="taggable-item" data-initial-tags="Red, Blue, Green">
<p>Item with predefined tags</p>
<div class="item-tags"></div>
</div>
<!-- Using hex values -->
<div class="taggable-item" data-initial-tags="#ec8383, #84cdef">
<p>Item with hex-defined tags</p>
<div class="item-tags"></div>
</div>
<!-- Mixed approach -->
<div class="taggable-item" data-initial-tags="Yellow, #ca99de">
<p>Item with mixed tag definitions</p>
<div class="item-tags"></div>
</div>Initial tags are applied during initialization and don't trigger events.
ColorTag provides event hooks for tag operations:
// Subscribe to tag added event
colorTag.on('tagAdded', (data) => {
console.log(`Tag added: ${data.colorName} (${data.color}) to ${data.itemId}`);
// Save to database, update UI, etc.
});
// Subscribe to tag removed event
colorTag.on('tagRemoved', (data) => {
console.log(`Tag removed: ${data.colorName} from ${data.itemId}`);
// Update database, refresh UI, etc.
});
// Unsubscribe from events
const myHandler = (data) => { /* ... */ };
colorTag.on('tagAdded', myHandler);
colorTag.off('tagAdded', myHandler);The event callbacks receive a data object with the following properties:
tagAdded Event:
itemElement: Reference to the DOM elementitemId: ID of the element (or generated unique ID)tagElement: Reference to the created tag DOM elementcolor: Hex value of the color (e.g., "#ec8383")colorName: Name of the color (e.g., "Red")timestamp: When the tag was added
tagRemoved Event:
itemElement: Reference to the DOM elementitemId: ID of the element (or generated unique ID)color: Hex value of the colorcolorName: Name of the colortimestamp: When the tag was removed
colortag.js/
├── css/
│ └── style.css # Styles for the color tags and UI
├── js/
│ └── colortag.js # Main library code
├── index.html # Example/demo page
├── README.md # This documentation
├── LICENSE # MIT license
├── .gitignore # Git ignore file
└── CONTRIBUTING.md # Contribution guidelines
The ColorTag constructor accepts an options object:
const colorTag = new ColorTag({
// All options are optional
colors: [...], // Array of colors (objects or strings)
taggableItemClass: '...', // CSS class for taggable items
itemTagsClass: '...' // CSS class for tag containers
});Initializes ColorTag on matching elements.
- Parameters:
selectorOrOptions(optional): Either a CSS selector string or an options object:{ selector: '.my-selector', // CSS selector colors: ['#FF0000', ...] // Array of colors }
colors(optional): Array of colors to use for this initialization
- Returns: Number of initialized elements
- Examples:
// With selector only const count = colorTag.init('.documents .file'); // With colors array as second parameter colorTag.init('.documents', ['#FF0000', '#00FF00']); // With options object colorTag.init({ selector: '.documents', colors: [ { name: 'Critical', color: '#FF0000' }, { name: 'Normal', color: '#00FF00' } ] });
Subscribes to an event.
- Parameters:
eventName: 'tagAdded' or 'tagRemoved'callback: Function to call when event occurs
- Returns: Boolean indicating success
- Example:
colorTag.on('tagAdded', (data) => { updateDatabase(data.itemId, data.colorName); });
Unsubscribes from an event.
- Parameters:
eventName: 'tagAdded' or 'tagRemoved'callback: The function to remove
- Returns: Boolean indicating success
- Example:
const handler = (data) => { /* ... */ }; colorTag.on('tagRemoved', handler); // Later: colorTag.off('tagRemoved', handler);
ColorTag generates the following structure:
<div class="taggable-item">
<!-- Add Tag Button (added by ColorTag) -->
<button class="item-add-tag-button">
<svg class="plus-icon">...</svg>
</button>
<!-- Content (your existing content) -->
<p>Your content here</p>
<!-- Tag Container (your existing container or added by ColorTag) -->
<div class="item-tags">
<!-- Applied Tags (added when tags are applied) -->
<div class="applied-tag" data-color="#ec8383" data-color-name="Red" style="background-color: #ec8383;"></div>
<div class="applied-tag" data-color="#84cdef" data-color-name="Blue" style="background-color: #84cdef;"></div>
</div>
<!-- Color Palette (added by ColorTag, toggled when button is clicked) -->
<div class="item-color-palette">
<div class="color-tag-option" data-color="#c8c8c8" data-color-name="Gray"></div>
<div class="color-tag-option" data-color="#ec8383" data-color-name="Red"></div>
<!-- etc. -->
</div>
</div>const colorTag = new ColorTag();
// Initialize documents with document-specific colors
colorTag.init('.documents', [
{ name: 'Draft', color: '#AAAAAA' },
{ name: 'Review', color: '#FFCC00' },
{ name: 'Approved', color: '#66CC33' },
{ name: 'Rejected', color: '#CC3333' }
]);
// Initialize tasks with priority colors
colorTag.init('.tasks', [
{ name: 'Low', color: '#33CC33' },
{ name: 'Medium', color: '#FFCC00' },
{ name: 'High', color: '#FF9900' },
{ name: 'Critical', color: '#CC3333' }
]);// Fetch color configuration from server
fetch('/api/user-colors')
.then(response => response.json())
.then(colorData => {
const colorTag = new ColorTag();
// Apply the user's custom colors
colorTag.init('.user-content', colorData.colors);
});ColorTag is compatible with modern browsers:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers with touch support
-
Desktop/Mouse:
- Click the "+" button to show color palette
- Click a color to add a tag
- Hover over a tag to see the "X" remove button
- Click the "X" to remove a tag
-
Mobile/Touch:
- Tap the "+" button to show color palette
- Tap a color to add a tag
- Tap directly on a tag to remove it
ColorTag provides full keyboard navigation support for accessibility:
- Tab to navigate to the "+" (add tag) button
- Enter or Space to open the color palette
- Escape to close an open palette and return focus to the button
- When a palette opens, focus automatically moves to the first color option
- Arrow Keys to navigate between color options:
- → (Right) or ↓ (Down): Move to next color
- ← (Left) or ↑ (Up): Move to previous color
- Enter or Space to select a color and add the tag
- Escape to close the palette and return focus to the add button
- Navigation wraps around (last color → first color, and vice versa)
- Tab to navigate to existing applied tags
- Enter, Space, Delete, or Backspace to remove a tag
- Each tag announces its color name to screen readers
- All buttons and interactive elements have proper ARIA labels
- Color information is available to assistive technologies
- Proper roles and states are announced (expanded/collapsed palettes)
- Focus management ensures users always know where they are
- Clear blue outline (2px solid #007AFF) on all focused elements
- Consistent focus styling across all interactive components
- Focus indicators are visible and meet accessibility contrast requirements
- Tab to reach an add tag button
- Enter to open the color palette
- Arrow keys to select desired color
- Enter to apply the color tag
- Tab to navigate to applied tags
- Delete to remove unwanted tags
This keyboard support ensures the library is fully accessible to users who rely on keyboard navigation or assistive technologies.
Future versions will include CSS variables for easier styling.
You can override the CSS classes in css/style.css to customize appearance.
Contributions are welcome! Please feel free to submit a Pull Request. See CONTRIBUTING.md for details.
This project is licensed under the MIT License - see the LICENSE file for details.