readmore-lines
v1.0.1
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. Unlike other readmore libraries this one is based on number of lines of text instead of number of words or symbols. Features automatic caching, smooth animations, and comprehensive browser support.

Contents
- Features
- Installation
- Quick Start
- API Reference
- Styling
- Accessibility Features
- Browser Support
- Build Outputs
- Performance
- Examples
- Development
- Contributing
- License
- Changelog
- 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
v1.0.1
- Contents in readme
- Updated dependencies
- Fix in build process
Support
If you encounter any issues or have questions, please file an issue on GitHub.
Made with ❤️ by Konstantin Agafonov
