A lightweight jQuery plugin for collapsing and expanding long blocks of text with "Read more" and "Close" links.

Overview

Readmore.js V3 alpha

I am deprecating the 2.x version of Readmore.js. A new version is coming soon! Check it out and help me test it!


Readmore.js

A smooth, responsive jQuery plugin for collapsing and expanding long blocks of text with "Read more" and "Close" links.

The markup Readmore.js requires is so simple, you can probably use it with your existing HTML—there's no need for complicated sets of div's or hardcoded classes, just call .readmore() on the element containing your block of text and Readmore.js takes care of the rest. Readmore.js plays well in a responsive environment, too.

Readmore.js is tested with—and supported on—all versions of jQuery greater than 1.9.1. All the "good" browsers are supported, as well as IE10+; IE8 & 9 should work, but are not supported and the experience will not be ideal.

Install

Install Readmore.js with npm:

$ npm install readmore-js

Then include it in your HTML:

<script src="/node_modules/readmore-js/readmore.min.js"></script>

Or, using Webpack or Browserify:

require('readmore-js');

Use

$('article').readmore();

It's that simple. You can change the speed of the animation, the height of the collapsed block, and the open and close elements.

$('article').readmore({
  speed: 75,
  lessLink: '<a href="#">Read less</a>'
});

The options:

  • speed: 100 in milliseconds
  • collapsedHeight: 200 in pixels
  • heightMargin: 16 in pixels, avoids collapsing blocks that are only slightly larger than collapsedHeight
  • moreLink: '<a href="#">Read more</a>'
  • lessLink: '<a href="#">Close</a>'
  • embedCSS: true insert required CSS dynamically, set this to false if you include the necessary CSS in a stylesheet
  • blockCSS: 'display: block; width: 100%;' sets the styling of the blocks, ignored if embedCSS is false
  • startOpen: false do not immediately truncate, start in the fully opened position
  • beforeToggle: function() {} called after a more or less link is clicked, but before the block is collapsed or expanded
  • afterToggle: function() {} called after the block is collapsed or expanded
  • blockProcessed: function() {} called once per block during initilization after Readmore.js has processed the block.

If the element has a max-height CSS property, Readmore.js will use that value rather than the value of the collapsedHeight option.

The callbacks:

The beforeToggle and afterToggle callbacks both receive the same arguments: trigger, element, and expanded.

  • trigger: the "Read more" or "Close" element that was clicked
  • element: the block that is being collapsed or expanded
  • expanded: Boolean; true means the block is expanded

The blockProcessed callback receives element and collapsable.

  • element: the block that has just been processed
  • collapsable: Boolean; false means the block was shorter than the specified minimum collapsedHeight--the block will not have a "Read more" link

Callback example:

Here's an example of how you could use the afterToggle callback to scroll back to the top of a block when the "Close" link is clicked.

$('article').readmore({
  afterToggle: function(trigger, element, expanded) {
    if(! expanded) { // The "Close" link was clicked
      $('html, body').animate( { scrollTop: element.offset().top }, {duration: 100 } );
    }
  }
});

Removing Readmore:

You can remove the Readmore.js functionality like so:

$('article').readmore('destroy');

Or, you can be more surgical by specifying a particular element:

$('article:first').readmore('destroy');

Toggling blocks programmatically:

You can toggle a block from code:

$('article:nth-of-type(3)').readmore('toggle');

CSS:

Readmore.js is designed to use CSS for as much functionality as possible: collapsed height can be set in CSS with the max-height property; "collapsing" is achieved by setting overflow: hidden on the containing block and changing the height property; and, finally, the expanding/collapsing animation is done with CSS3 transitions.

By default, Readmore.js inserts the following CSS, in addition to some transition-related rules:

selector + [data-readmore-toggle], selector[data-readmore] {
  display: block;
  width: 100%;
}

selector would be the element you invoked readmore() on, e.g.: $('selector').readmore()

You can override the base rules when you set up Readmore.js like so:

$('article').readmore({blockCSS: 'display: inline-block; width: 50%;'});

If you want to include the necessary styling in your site's stylesheet, you can disable the dynamic embedding by setting embedCSS to false:

$('article').readmore({embedCSS: false});

Media queries and other CSS tricks:

If you wanted to set a maxHeight based on lines, you could do so in CSS with something like:

body {
  font: 16px/1.5 sans-serif;
}

/* Show only 4 lines in smaller screens */
article {
  max-height: 6em; /* (4 * 1.5 = 6) */
}

Then, with a media query you could change the number of lines shown, like so:

/* Show 8 lines on larger screens */
@media screen and (min-width: 640px) {
  article {
    max-height: 12em;
  }
}

Contributing

Pull requests are always welcome, but not all suggested features will get merged. Feel free to contact me if you have an idea for a feature.

Pull requests should include the minified script and this readme and the demo HTML should be updated with descriptions of your new feature.

You'll need NPM:

$ npm install

Which will install the necessary development dependencies. Then, to build the minified script:

$ npm run build
Comments
  • Text being cut off.

    Text being cut off.

    image

    I can't figure out why, but in the expanded view on one section, the text is cut off. If I resize to a smaller screen dimension, this one is fixed as you can see here:

    image

    however, it breaks another one that was working at full size. Can you help me figure out why this is?

    image

    fixed in 2.0 
    opened by ghost 13
  • Doesn't work on ES6

    Doesn't work on ES6

    Using ES6, when importing using import 'readmore-js', I am getting this error:

    TypeError: (0 , _jquery2.default)(...).readmore is not a function(…)

    I believe this is a problem with code that requires a global variable. Any ideas on fixes?

    More info needed 
    opened by zsaraf 10
  • Ignoring CSS max-height

    Ignoring CSS max-height

    Hi there,

    I'm trying to use readmore.js with a div and the CSS max-height property as follows:

    .category-description { margin:0 0 10px; max-height: 100px; }

    jQuery(document).ready(function(){

    if(jQuery('.category-description')) {
        jQuery('.category-description').readmore({
            speed: 400,
            moreLink: '<a href="#">>> weiterlesen</a>',
            lessLink: '<a href="#"><< weniger</a>'
        });
    }
    

    }

    But it doesn't work because readmore.js ignores/overwrites the max-height CSS setting and uses the standard 200px:

    Do you have any suggestions?

    Thanks Amos

    opened by amosgroth 8
  • Is there a way to create an AngularJS directive?

    Is there a way to create an AngularJS directive?

    I want to use Readmore.js with AngularJS. It works partially only with the initial/default values. I can't pass options.

    I've tried it with Angular-UI jQuery Passthrough (http://angular-ui.github.io/ui-utils/#/jq)

    <div id="disclaimer" ui-jq="readmore">
    [...]
    
    .value('uiJqConfig', {
            // The jQuery Plugin namespace
            readmore: {
                // Readmore options. This object will be used as the defaults
                speed: 1000,
                embedCSS: false,
                moreLink: '<div class="horizontal-line"><span class="line-center arrow-down">Kompletten Disclaimer anzeigen</span></div>',
                lessLink: '<div class="horizontal-line"><span class="line-center arrow-up">Disclaimer schließen</span></div>'
            }
        })
    

    But only the default values are applied ('Read more', 'Close').

    And I also developed a directive by myself:

    <div id="disclaimer" bs-readmore>
    [...]
    
    .directive('bsReadmore', ['$log',
                function ($log) {
            return {
                link: function (scope, element, attrs) {
                    //$log.log(scope, element, attrs);
                    $(element).readmore({
                        speed: 1000,
                        embedCSS: false,
                        moreLink: '<div class="horizontal-line"><span class="line-center arrow-down">Kompletten Disclaimer anzeigen</span></div>',
                        lessLink: '<div class="horizontal-line"><span class="line-center arrow-up">Disclaimer schließen</span></div>'
                    });
                }
            };
        }])
    

    Same behavior as before. My Options won't be applied.

    Is there some magic, which I didn't see?

    opened by exislow 8
  • Problem with height of expanded section

    Problem with height of expanded section

    Hi Jed, When I tested this on my site, the expanded section height is stuck at 758, which is cutting off the content on one of my articles--I attached a screenshot of the code from Firebug. I tired several different places to change this, but I don't understand where that value is coming from. Please let me know how I can customize the maximum height value for the expanded section.

    The class reference that I see for the section in Firebug is combining two classes. I tried emulating that in my stylesheet, but it had no effect.

    Thanks!

    Jeremy screen shot 2014-02-19 at 12 06 59 pm

    opened by suhr-ireland 8
  • Weird behaviour in Safari on iPhone

    Weird behaviour in Safari on iPhone

    We implemented Readmore.js on the following page: https://www.paardenarts.nl/stories/ruby/ (click "Volledig achtergrondverhaal"). We used the following jQuery code to implement it:

    $('[data-read-more]').readmore({
      speed: 400,
      collapsedHeight: 122,
      moreLink: '<p class="read-more-link"><a href="#">Volledig achtergrondverhaal</a></p>',
      lessLink: '<p><a href="#">Sluiten</a></p>'
    });
    

    When you open the page on an iPhone and you click "Volledig achtergrondverhaal" and scroll after it opened it closes again, but leaves the close link visible.

    Can you please help me fix this?

    opened by janhenkes 7
  • Expanded elements collapse when scrolling on iphone 6 safari and chrome

    Expanded elements collapse when scrolling on iphone 6 safari and chrome

    Hi, Implemented readmore for long paragraphs. Expand and collapse work fine, however when scrolling the page down on a expanded element (a

    ), it automatically collapses. Debugged my js and did'nt find any triggering of the load event. any idea?

    opened by D0cNet 7
  • Not works for DIVs which are initially invisible

    Not works for DIVs which are initially invisible

    If my div has style "display: none" when page loads, readmore() not works for this div. Here is the example: http://jsfiddle.net/samsonbek/hubusf30/

    height calc of invisible content 
    opened by samsonbek 7
  • Broken in Safari with an iframe

    Broken in Safari with an iframe

    Thanks much for Readmore.js! It works great but we noticed a problem. If there is an iframe inside a div, then Readmore.js does not display the contents of iframe on Safari. On other browsers (Chrome/Firefox) it works fine. On OSX or iOS Safari the iframe contents are not rendered.

    Any idea what might be causing this behavior?

    Plunker which shows the problem

    I have a plunker which demonstrates this problem: http://plnkr.co/edit/SCr7jmwmxQYrsTfDvsIY?p=preview

    On Safari you see:

    screen shot 2015-06-21 at 10 50 11 am

    On Chrome/Firefox you see:

    screen shot 2015-06-21 at 10 49 54 am

    opened by ayush 7
  • Readmore doesn't work from time to time

    Readmore doesn't work from time to time

    Readmore sometimes doesn't work. There's no errors in console. Tested in Chrome 44.0.2403.30 beta-m, FF 34.0.5.

    Initialization

    $('.desc_in').readmore({
            speed: 300,
            maxHeight: 280,
            moreLink: '<a href="#" class="desc_more openmore">читать далее</a>',
            lessLink: '<a href="#" class="desc_more closemore">Скрыть</a>'
        });
    

    Height of this blocks is more than 280px

    Examples readmore_not_ok readmore_ok

    More info needed 
    opened by TheRulisp 6
  • Issue with using the readmore.js with rows of divs in bootstrap

    Issue with using the readmore.js with rows of divs in bootstrap

    I am using bootstrap and have a row with multiple div blocks. I want to use the readmore.js functionality for this section.

    I try to surround the content I want with the article tags but it is not working. I amusing the tag on other text and it works like a charm.

    I can send you a link to give you more information if you would like.

    More info needed 
    opened by thesteviep 6
  • Fix a bug caused by the .selector property being deprecated in jQuery 3.0

    Fix a bug caused by the .selector property being deprecated in jQuery 3.0

    This fixes issue #161 caused by jQuery 3.0 having deprecated the .selector property. Because of this, those using jQuery 3.0 in concert with Readmore.js should specify the selector property for each initialization of Readmore.js on an element. Example below:

    $('#readmore-section').readmore({
      selector: '#readmore-section'
    });
    
    opened by madisonmanhire 0
  • Tailwind support for max-h-[none]

    Tailwind support for max-h-[none]

    If I set a maximum height of none should this disable the readmore behaviour?

    E.g: <div class="truncate lg:whitespace-normal max-h-24 lg:max-h-[none]">Lorem ipsum

    opened by howdu 0
  • Link is created but not clickable on Galaxy a21s

    Link is created but not clickable on Galaxy a21s

    For some reason, just on the Galaxy a21s the click isn't working to slide the content. No issues on other devices, not sure why this is the case yet. Currently investigating.

    opened by wplit 0
  • Remove height and maxHeight entirely on destroy()

    Remove height and maxHeight entirely on destroy()

    Setting them to "initial" breaks the automatic maxHeight (set by the CSS) pickup. E.g. if the max-height set in the CSS uses relative units (rem, %, vh, vw, etc.), you want to "refresh" the readmore block on resize by destroying it and then initializing it again. That is currently impossible without clearing styles manually like so:

            const $el = readMore.elements[0];  
            readMore.destroy(readMore.elements[0]);  
            $el.style.height = '';  
            $el.style.maxHeight = '';  
    
    opened by tadaskarpavicius 0
  • What is the best way to import it in webpack

    What is the best way to import it in webpack

    Hello, i'm wondering what is the best way to import it in js ?

    import readmore from 'readmore-js';
    import readmore-js from 'readmore-js';
    import Readmore from 'readmore-js'; 
    

    Thanks a lot, great plugin !

    opened by ametthey 2
  • Releases(2.2.1)
    • 2.2.1(Sep 22, 2018)

    • v2.2.0(May 13, 2016)

      Fixes

      • Issues with _this in toggle method (#131)
      • Loosened dependency on jQuery, fixes getting multiple versions of jQuery when bundling with Browserify (#146)
      • Added jQuery as a Bower dependency (#127)

      Improvements

      • Added blockProcessed callback function (#136)
      • Added the block's ID as the value of the data-readmore-toggle attribute of "Read more" and "Close" links, allowing greater visibility into exactly what block was toggled (#142)
      • Wrap the Gulp compress task in npm build script ($ npm run build)
      Source code(tar.gz)
      Source code(zip)
    • v2.1.0(Nov 1, 2015)

      Improvements

      • Added CommonJS/AMD support (Thanks to @joshua703 and @mattmattmatt)
      • Published to npm as readmore-js; Bower is still available, but npm is now preferred
      • Fixed a bug with how startOpen worked (Thanks @arusahni)
      • The element argument to the before and afterToggle callbacks is now a jQuery object
      • Added MIT license
      Source code(tar.gz)
      Source code(zip)
    • v2.0.5(Feb 16, 2015)

    • v2.0.2(Feb 2, 2015)

      Fixes

      • Rolled back calling init() on window.load, instead, init is called immediately and resizeBoxes is called on window.load. Should address #76
      Source code(tar.gz)
      Source code(zip)
    • v2.0.0(Jan 3, 2015)

      New features

      • Install with Bower: bower install readmore
      • Blocks can now be toggled programmatically: $('article:nth-of-type(3)').readmore('toggle')
      • ARIA semantics describe expanded state and relationship between blocks and their toggles
      • Blocks are now assigned an ID if they don't already have one
      • Install development dependencies with NPM
      • Gulp task to minifiy with UglifyJS

      Improvements

      • Height calculations on window resize are "debounced", resulting in more efficient rendering
      • Height calculation in general has been improved
      • The value of the expanded argument passed to the beforeToggle callback now correctly reflects the pre-toggle state
      • Multiple instances are now fully supported: e.g. $('article').readmore({speed: 200}) and $('fieldset').readmore({speed: 900}) will work on the same page
      • Fully responsive, plugin now prefers max-heights set in CSS, even inside media queries

      Potentially breaking changes

      • maxHeight option is now collapsedHeight
      • sectionCSS option is now blockCSS
      • toggleSlider() method is now just toggle()
      • Animation is now performed with CSS3 transitions, rather than jQuery.animate()
      • IE 8 and 9 are no longer supported, because those browsers hate kittens
      • init() is now called within a window.onload event handler, which can briefly delay collapsing content
      • setBoxHeight() is now a "private" method called setBoxHeights()
      • resizeBoxes() is also now private
      • Readmore.js now uses attribute selectors, rather than classes
        • The .readmore-js-section and .readmore-js-toggle classes are gone
        • The expandedClass and collapsedClass options are also gone
        • Every Readmore.js block needs an ID, if one is not already present, one will be generated
      Source code(tar.gz)
      Source code(zip)
    An easy to use, yet advanced and fully customizable javascript/jQuery paginator plugin

    anyPaginator An easy to use, yet advanced and fully customizable Javascript/jQuery paginator plugin. anyPaginator is a spinoff of the anyList project

    Arne Morken 2 Feb 17, 2022
    FriendAdvisor is a mobile app with a focus on allowing friends and family to coordinate and receive text notifications about upcoming group events.

    FriendAdvisor is a mobile app with a focus on allowing friends and family to coordinate and receive text notifications about upcoming group events.

    Brad Johnson 4 Sep 29, 2022
    Translate text to morse code, but the morse code is emojis

    morsemoji Convert text to morse code... with emojis! Check it out! This project was built with React, Vite, Emoji Mart, Nord, and react-copy-to-clipbo

    Cassidy Williams 48 Jul 21, 2022
    A very lightweight and chatbot with multi language support

    A very lightweight and chatbot with multi language support

    Artificial Intelligence 6 Jul 25, 2022
    A lightweight, fast and efficient Discord Nitro sniper, giveaway sniper & invite sniper

    Discord Sniper (forked from slow/nitro-sniper) A lightweight, fast and efficient Discord Nitro sniper, giveaway sniper & invite sniper. Features Nitro

    null 3 Oct 23, 2022
    NatsirtMC is a lightweight app allowing you to connect to any Minecraft server without having Minecraft open

    NatsirtMC the only way to grind without grinding NatsirtMC is a lightweight app allowing you to connect to any Minecraft server without having Minecra

    tristan 3 Dec 26, 2022
    A jump-start for jQuery plugins development

    jQuery Boilerplate A jump-start for jQuery plugins development So, you've tried your hand at writing jQuery plugins and you're comfortable putting tog

    jQuery Boilerplate 2.5k Dec 20, 2022
    Gmail-like client-side drafts and bit more. Plugin developed to save html forms data to LocalStorage to restore them after browser crashes, tabs closings and other disasters.

    Sisyphus Plugin developed to save html forms data to LocalStorage to restore them after browser crashes, tabs closings and other disasters. Descriptio

    Alexander Kaupanin 2k Dec 8, 2022
    a responsive equal heights plugin

    jquery.matchHeight.js matchHeight makes the height of all selected elements exactly equal brm.io/jquery-match-height Demo - Features - Gallery - Insta

    null 3.1k Jan 5, 2023
    BetterDiscord plugin to see what your friends are playing across platforms, all on Discord

    CrossPlatformPlaying A plugin that brings Rich Presence to games that don't support it, and lets you see what your friends are playing even if they tu

    Giorgio 38 Dec 12, 2022
    yt-dlp extractor plugin for DisTube.js.org.

    yt-dlp extractor plugin for DisTube.js.org.

    DisTube 6 Jul 17, 2022
    A feature rich message noting plugin for Cumcord

    Sperm Bank A feature rich message noting plugin for Cumcord. Features The ability to add messages to a virtual "account" The ability to make multiple

    SwishyPlugs 8 Nov 30, 2022
    The perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on existing HTML.

    List.js Perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on

    Jonny Strömberg 10.9k Jan 1, 2023
    Drag and drop library for two-dimensional, resizable and responsive lists

    GridList Drag and drop library for a two-dimensional resizable and responsive list of items Demo: http://hootsuite.github.io/grid/ The GridList librar

    Hootsuite 3.6k Dec 14, 2022
    Defines the communication layer between mobile native(iOS/Android) and webview using JSON Schema and automatically generates SDK code

    Defines the communication layer between mobile native(iOS/Android) and webview using JSON Schema and automatically generates SDK code.

    당근마켓 31 Dec 8, 2022
    A responsive image polyfill for , srcset, sizes, and more

    Picturefill A responsive image polyfill. Authors: See Authors.txt License: MIT Picturefill has three versions: Version 1 mimics the Picture element pa

    Scott Jehl 10k Dec 31, 2022
    A high-performance, dependency-free library for animated filtering, sorting, insertion, removal and more

    MixItUp 3 MixItUp is a high-performance, dependency-free library for animated DOM manipulation, giving you the power to filter, sort, add and remove D

    Patrick Kunka 4.5k Dec 24, 2022
    JavaScript Survey and Form Library

    SurveyJS is a JavaScript Survey and Form Library. SurveyJS is a modern way to add surveys and forms to your website. It has versions for Angular, jQue

    SurveyJS 3.5k Jan 1, 2023
    Extensive math expression evaluator library for JavaScript and Node.js

    ?? Homepage Fcaljs is an extensive math expression evaluator library for JavaScript and Node.js. Using fcal, you can perform basic arithmetic, percent

    Santhosh Kumar 93 Dec 19, 2022