readmore-lines
v1.0.0
Published
A lightweight JavaScript library for creating 'read more/read less' functionality with text truncation
Maintainers
Readme
ReadMore.js
A lightweight, high-performance JavaScript library for creating "read more/read less" functionality with text truncation. Features automatic caching, smooth animations, and comprehensive browser support.
Features
- 🚀 High Performance: Cached line height calculations and CSS styles
- 🧠 Smart Caching: Automatic memory management with WeakMap
- 📱 Responsive: Works with any text content and container size
- ♿ Accessible: ARIA attributes, keyboard navigation, and semantic HTML
- 🎨 Customizable: Flexible styling and configuration options
- 📦 Lightweight: No external dependencies, ~3KB minified
Installation
npm
npm install readmore-linesyarn
yarn add readmore-linesCDN
<!-- Development version (unminified) -->
<script src="https://unpkg.com/readmore-lines@latest/dist/readmore.js"></script>
<!-- Production version (minified) -->
<script src="https://unpkg.com/readmore-lines@latest/dist/readmore.min.js"></script>UMD usage (script tag)
When using the UMD build via a script tag, the global is a callable function. Call it as readmore(...):
<div id="my-text">Long content here...</div>
<script src="./dist/readmore.js"></script>
<script>
readmore({ targetElement: document.getElementById('my-text'), linesLimit: 4 });
// Utilities are available on the same namespace:
// readmore.destroyReadMore(...)
</script>Quick Start
Basic Usage
import readmore from 'readmore-lines';
// Simple implementation
readmore({
targetElement: document.getElementById('my-text')
});API Reference
readmore(options)
The main function that implements the read more/less functionality.
Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| targetElement | HTMLElement | ✅ | - | The DOM element to apply readmore functionality to |
| readMoreLabel | string | ❌ | 'Read more...' | Text for the "read more" link |
| readLessLabel | string | ❌ | 'Read less' | Text for the "read less" link |
| targetClass | string | ❌ | 'read-more-target' | CSS class applied to the target element |
| linkClass | string | ❌ | 'read-more-link' | CSS class applied to the toggle link |
| linesLimit | number | ❌ | 8 | Maximum number of lines before truncating |
Example
readmore({
targetElement: document.getElementById('article-content'),
readMoreLabel: 'Continue reading...',
readLessLabel: 'Show less',
linesLimit: 5,
targetClass: 'article-truncate',
linkClass: 'read-more-button'
});Styling
Default Styles
The library automatically adds CSS for text truncation:
.read-more-target {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 8; /* or your specified linesLimit */
-webkit-box-orient: vertical;
}Custom Styling
You can customize the appearance by targeting the generated classes:
.read-more-target {
/* Your custom truncation styles */
}
.read-more-link {
color: #007bff;
text-decoration: none;
font-weight: bold;
}
.read-more-link:hover {
text-decoration: underline;
}Accessibility Features
ARIA Support
- aria-expanded: Automatically updates to reflect content state
- aria-controls: Links button to controlled content
- role="button": Proper semantic role for screen readers
Keyboard Navigation
- Enter key: Activates the toggle functionality
- Space key: Activates the toggle functionality
- Tab navigation: Button is focusable and follows tab order
Semantic HTML
- Uses
<button>element instead of<a>for better semantics - Automatically assigns unique IDs for proper ARIA relationships
- Maintains focus management during interactions
Browser Support
- Chrome 6+
- Firefox 3.6+
- Safari 5+
- Edge 12+
- IE 9+ (with polyfills for
WeakMap)
Build Outputs
The library provides multiple build formats for different use cases:
| File | Size | Description |
|------|------|-------------|
| readmore.js | ~11KB | Development version (unminified, with sourcemap) |
| readmore.min.js | ~2.5KB | Production version (minified, optimized) |
| readmore.esm.js | ~10KB | ES Module version |
File Size Comparison
- Unminified: ~11KB (readable, with comments)
- Minified: ~2.5KB (77% size reduction)
- Gzipped: ~1.2KB (estimated)
Performance
Caching System
- CSS Caching: Prevents duplicate style additions
- Line Height Caching: Caches computed line heights per element
- Memory Management: Uses WeakMap for automatic garbage collection
Optimization Features
- Efficient line height calculations
- Minimal DOM queries
- Automatic cache invalidation
Examples
Multiple Elements
// Apply to multiple elements efficiently
document.querySelectorAll('.truncate').forEach(element => {
readmore({
targetElement: element,
linesLimit: 3
});
});Custom Styling
<style>
.my-custom-truncate {
background: linear-gradient(to bottom, transparent 0%, white 100%);
}
.my-custom-link {
background: #007bff;
color: white;
padding: 5px 10px;
border-radius: 3px;
text-decoration: none;
}
</style>
<script>
readmore({
targetElement: document.getElementById('content'),
targetClass: 'my-custom-truncate',
linkClass: 'my-custom-link',
readMoreLabel: 'Read Full Article',
readLessLabel: 'Collapse'
});
</script>Cleanup and Instance Management
import readmore, {
destroyReadMore,
hasReadMoreInstance,
getReadMoreInstance,
} from 'readmore-lines';
// Check if element has readmore functionality
if (hasReadMoreInstance(element)) {
console.log('Element has readmore functionality');
}
// Get the instance for advanced control
const instance = getReadMoreInstance(element);
if (instance) {
console.log('Instance configuration:', instance.config);
}
// Destroy readmore functionality and clean up resources
destroyReadMore(element);
// Clear all CSS cache (useful for complete reset)
clearReadMoreCache();Dynamic Content Management
// Handle dynamic content updates
function updateContent(element, newContent) {
// Destroy existing readmore if present
if (hasReadMoreInstance(element)) {
destroyReadMore(element);
}
// Update content
element.innerHTML = newContent;
// Reapply readmore functionality
readmore({
targetElement: element,
linesLimit: 4
});
}
// Handle style changes that affect line height
function updateElementStyles(element) {
// Apply new styles
element.style.fontSize = '18px';
element.style.lineHeight = '1.5';
// Recalculate if readmore is active
if (hasReadMoreInstance(element)) {
const instance = getReadMoreInstance(element);
// Force recalculation by destroying and recreating
destroyReadMore(element);
readmore({
targetElement: element,
linesLimit: instance.config.linesLimit
});
}
}Development
Building
# Install dependencies
npm install
# Build all versions (development + production)
npm run build
# Build development version only (unminified)
npm run build:dev
# Build production version only (minified)
npm run build:prod
# Run tests
npm test
# Lint code
npm run lintProject Structure
readmore-lines/
├── src/
│ ├── readmore.js # Main library file
│ └── readmore.d.ts # TypeScript declarations
├── dist/ # Built files
│ ├── readmore.js # Development build (unminified)
│ ├── readmore.min.js # Production build (minified)
│ ├── readmore.esm.js # ES Module build
│ └── *.map # Source maps
├── tests/ # Test files
├── package.json
├── rollup.config.js
└── README.mdContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
v1.0.0
- Initial release
- Core readmore functionality
- CSS and line height caching
- TypeScript support
- Comprehensive documentation
Support
If you encounter any issues or have questions, please file an issue on GitHub.
Made with ❤️ by Konstantin Agafonov
