No code required

As much as we F'n LOVE javascript at Finsweet, we know who our market is.

Introducing Visual Script Writer!

There are many people who don't want to write javascript and have zero interest learning. No problem — we made a Visual Script Writer just for you. You don't have to write a single line of code to use this Library. You can generate 100% of the code visually.

Please make sure you are sitting down when you click the button blow. It is really F'in sweet.
Grab it here

For others who are interested in learning javascript - we have deep explanations, step by step walkthroughs, and all that jazz. We built this training around teaching you basics of javascript. If you want to take your Webflow skills to the next level, learn javascript.

If you read the docs, follow the walkthroughs, and really learn how this F'in sweet CMS Library works, you'll also learn the basics of javascript and the building blocks of using most javascript libraries.

Let's learn... and do F'in sweet stuff with Webflow CMS :)

Get Started

Add F’in sweet CMS Library to your page

The very first step is to put the library script on the page. The link below is a CDN hosted javascript file free for you to use. You may also upload the script file to your own server

<script src="https://cdn.finsweet.com/files/cmslibrary-v1.2.js"></script>
Copy code

We recommend adding this Library before the closing<body></body> tag of the page. CMS Library has no dependencies, so you can put the code in the <head></head> if you need. If you have no reason to put it in the <head></head>,  go for the<body></body>

Create a new instance of the Library

Create a new Library instance just below the Library script. Use this function if you are putting your code in the <body></body> (recommended)

<script src="https://cdn.finsweet.com/files/cmslibrary-v1.2.js"></script>

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"

  var customBlogPosts = new FsLibrary('.blog-posts-list') // Collection List class

  // we're going to put our components here
})();
</script>
Copy code

Creating an instance establishes which Webflow dynamic list we are working with when using the components below. Adding components to your instance is flexible. You can add multiple components to the same FsLibrary instance. You can also create multiple instances of FsLibrary on the same page and use different library components on different instances. For example, you can run Add Classes on your customBlogPosts list and also run Filter and Combine on your availableJobs collection list.

Need your script in the <head></head> of the page? Use this function!

<script src="https://cdn.finsweet.com/files/cmslibrary-v1.2.js"></script>

<script>
// wait for the DOM to load and then run the function
document.addEventListener("DOMContentLoaded", function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"

  var customBlogPosts = new FsLibrary('.blog-posts-list') // Collection List class

  // we're going to put our components here

});
</script>
Copy code

Why is it different in the <head></head> ? This waits for the DOM to load before executing the javascript. We must wait for the DOM to load because we are trying to access elements in the DOM with our script.

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
new FsLibrary
How we create a new instance of FsLibrary. This name can not be customized. It must be 'new FsLibrary'
.blog-posts-list
The class we apply to the Webflow 'Collection List' that we want to use the Library on. Important: this is not the 'Collection List Wrapper' and not the 'Collection Item'. It is the middle element of a Dynamic List embed.

After we create our instance and store it in a variable, we add components.

Component #1

Combine

Combine Collection Items from multiple CMS Dynamic Lists into one single Collection List
Combined List
Collection List 1
Collection List 2
Collection Item

Use cases

Have more than 100 Collection Items in a single Collection List
You need to display more than 100 Collection Item in a single Collection List. This is extra helpful when you are running filters on a Collection List and need to prevent white space created from having multiple collection lists.
Put Collection Items from different CMS Collections in the same Collection List
For example you have CMS Collections for “Case Studies”, “Testimonials”, and “Blog Posts”. You want to users to be able to filter between all 3 Collection Lists in a single filter system.

How to use it

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // run the combine Library component on your instance
  customBlogPosts.combine()

})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance.

Important: Make sure all the Collection Lists that you want to combine have the same Collection List class (.blog-posts-list in our example).

Component #2

Load More

Load items from your Collection List on the same page.

Use cases

Prevent long load time
Your Collection has lots of Items. Maybe these Items also have 'heavy' graphics. The page may take too long to load and Load More may be necessary for a quick load experience
You want to use Pagination, but don't want to load a new page
Load the new items on the page page, directly under the already loaded Collection Items

How to use it

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // run the loadmore Library component on your instance
  customBlogPosts.loadmore({
    button: ".load-more-button", // class of Webflow Pagination button
    loadAll: true, // loads ALL items in your pagination list after the page loads
    animation: {
      enable: true,
      duration: .3,
      easing: 'ease',
      effects: 'fade'
    }
   })

})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
button
The class of the load more button that loads more Collection Items. This must be the native Webflow Paginate button

Cool: The button hides itself after there are no more items to load (NICE!).
loadAll
Loads all items inside Pagination. This can load all items inside a collection.

false = only load the first set of items in your pagination
true = load all of the items in your pagination.

If you have no reason to set loadAll to true, set to false.
animation
Option to add animations and transitions for items being loaded with the Load More button
enable
true turns on animation on, false turns animation off (default: true)
duration
Time the animation happens in seconds. 0.2 would be 0.2 seconds, or 200 milliseconds (default: 0.2)
easing
Easing of the effect. Available options are ease, ease-in, ease-out, and ease-in-out (default: ease)
effects
Add fade, translate, rotate, and scale effects. (default: fade)
Component #3

Filter

Filter Items in a Collection List based on text content inside the Item
Filter by

Use cases

Set up simple filtering systems with one filter group
Allow users to filter by Category, Service, Color, or any filter group you want.
Set up super complex filtering systems with many filter groups
Allow users to find exactly what they want in a long list of Collection Items

Setting up a filter

First, define your filter groups in an array. An array is a list!

<script>
// define 3 filter groups in an array and store it in a variable called myFilters

var myFilters = [
  {
    filterWrapper: ".filter-bar-category", // parent wrapper of filter group1
    filterType: "exclusive"
  },
  {
    filterWrapper: ".filter-bar-color", // parent wrapper of filter group2
    filterType: "multi"
  },
  {
    filterWrapper: ".filter-bar-service", // parent wrapper of filter group3
    filterType: "multi"
  }
]
</script>
Copy code

Then run the function below the array!

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // define 3 filter groups in an array and store it in a variable called myFilters
  var myFilters = [
    {
      filterWrapper: ".filter-bar-category", // parent wrapper of filter group1
      filterType: "exclusive"
    },
    {
      filterWrapper: ".filter-bar-color", // parent wrapper of filter group2
      filterType: "multi"
    },
    {
      filterWrapper: ".filter-bar-service", // parent wrapper of filter group3
      filterType: "multi"
    }
  ]

  // run the filter Library component on your instance
  
customBlogPosts.filter({
    filterArray: myFilters, // variable of the array we created above
    activeClass: 'button-active', // class that styles the active state
    
animation: {
      enable: false,
    }
  })
})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
var myFilters
A variable we established to store our array. This is variable holds all of our filter groups establishes how the filter groups work. You can name this variable anything you want
filterWrapper
The parent div wrapper holding the ui elements of a filter group
filterType
Can be exclusive or multi select specific to that filter group
exclusive
Allows the user to select 1 option inside the group at a time. The filter is exclusive to 1 option so for example clicking "red" would select all items with "red". If you then clicked "blue", "red" would be unselected
multi
Allows the user to select multiple options inside the group at a time so that clicking "red" would select items with "red". If you then clicked "blue", "red" would remain selected. Both options will be selected at the same time. The filtered grid would show results that match both "red" and "blue"
filterArray
Where we use our variable that holds  array we created. In the example, this would be myFilters
activeClass
The class that will be added to buttons when they are in an active state
animation
Option to add animations and transitions for items leaving and entering the filtered grid
enable
true turns on animation on, false turns animation off (default: true)
duration
Time in seconds the animation happens. 0.2 would be 0.2 seconds, or 200 milliseconds (default: 0.2)
easing
Easing of the effect. Available options are ease, ease-in, ease-out, and ease-in-out (default: ease)
effects
Add fade, translate, rotate, and scale effects. (default: fade)
filter-by
The data-attribute placed on the ui element to tell the Library what to filter by when that ui element is clicked.

HTML structure and data-attributes

HTML Structure
Create div wrappers for each filter group. Put all UI elements (buttons, search, checkbox, etc.) that control a filter group in their respective filter group div wrapper.
Here we have created 3 filter groups: .filter-bar-category, .filter-bar-color, and .filter-bar-service. These are the class names we put as the value of the filterWrapper option when we create our array. The UI elements that control the filtering of that group are children.

Filter buttons can be deep nested inside the parent wrapper. They don't have to be direct children. Check out the Checkbox nested-nested-nested inside .filter-bar-service.

We got you for full flexibility!
Data-attributes
Apply a filter-by data attribute to each filter button
We need to tell the Library what each button should filter by when it's clicked. We apply a data attribute with a name of 'filter-by' to each button that will update the filter. The "value" of that data attribute is the keyword that button will filter by.

A value of  *  will filter ALL items in that group (can be used to remove/reset the filter).

Types of html elements we can use to filter

<div></div>
'filter-by' is applied directly to the <div></div>.
<a> (link)</a>
'filter-by' is applied directly to the <a></a>.
<input> search
'filter-by' is applied directly to the <input> text field. Search bars always get "*" added as the value.
<select></select>
'filter-by' is applied to the <select></select> element and always gets a "*" value. The Value of the Choice is how each Choice is filtered by. The text visible to the user can be anything. In the above example "Blue color" is being filtered by the keyword "Blue".
<input> checkbox
'filter-by' is applied to the Checkbox element as seen in the screenshot.
<input> radio
'filter-by' is applied to the Radio Button element as seen in the screenshot.
comp-sort
Component #4

Sort

Sort Items in a Collection List based on text content inside the Item

Use cases

Set up custom sorts for users to control the data
Allow users to filter by Category, Service, Color, or any filter group you want.
Allow users to sort through items after they've applied filters
Allow users to find exactly what they want in a long list of Collection Items

How to use it

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // run the sort Library component on your instance
  
customBlogPosts.sort({
    sortTrigger: '.sort-button', // class of the button........
    sortReverse: true, // if you want sort first click to be Z>A.......
    activeClass: 'active', // class that styles the active state
    
animation: {
      duration: 0,
    }
  })
})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
sortTrigger
The class of the button that will be used to filter items. Clicking this button triggers the sort on your list.
sortReverse
Option to make the initial sort click reversed.

true = sort Z > A on first click
false = sort A > Z on first click

If your list is already sorted from A > Z and sortReverse is false, nothing will happen on the first click.
activeClass
The class that will be added to buttons when they are in an active state
animation
Option to add animations and transitions for items leaving and entering the filtered grid
enable
true turns on animation on, false turns animation off (default: true)
duration
Time in seconds the animation happens. 0.2 would be 0.2 seconds, or 200 milliseconds (default: 0.2)
easing
Easing of the effect. Available options are ease, ease-in, ease-out, and ease-in-out (default: ease)
effects
Add fade, translate, rotate, and scale effects. (default: fade)
sort-by
The data-attribute placed on the ui element to tell the Library what to sort by when that ui element is clicked.

Data-attributes

Data-attributes
Apply a sort-by data attribute to each sort button
We need to tell the Library what button is triggering the sort and what it should sort by.

Name is always sort-by

Value is the class of the text that button will filter by.

If you are filtering by the year, give a class of '.year-text' to the text element

Types of html elements we can use to filter

<div></div>
'sort-by' is applied directly to the <div></div>.
<a> (link)</a>
'sort-by' is applied directly to the<a></a>.
Component #5

Add Classes

Gives unique add-on classes to elements inside your Collection List

Use cases

Create unique layouts in minutes
Left/right flip layout
Everybody wants a left/right flipper
Crazy irregular cards
Go f'in crazy
Timeline
Timeline 100% managed via cms

How to use it

First, create an array to define the classes you’re targeting and the add-on classes. An array is a list! We're listing our add-on classes and where they will go.

<script>
// define 3 class pairings in an array and store it in a variable called flipSection
var flipSection = [
  {
    classTarget: ".project-feature", // the base class on the element
    classToAdd: ".flip-row" // the class you want to add to the element
  },
  {
    classTarget: ".project-feature-image",
    classToAdd: ".flip-image"
  }
]
</script>
Copy code

Then run the function below the array!

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // define 2 class pairings in an array and store it in a variable called flipSection
  
var flipSection = [
    {
      classTarget: ".project-feature", // the base class on the element
      classToAdd: ".flip-row" // the class you want to add to the element
    },
    {
      classTarget: ".project-feature-image",
      classToAdd: ".flip-image"
    }
  ]

  // run the addclass Library component on your instance
  customBlogPosts.addclasses({
    classArray: flipSection, // variable of the array we created above
    frequency: 3, // how often we add the classes in the Collection List
    start: 1 // when we start adding the classes in the Collection List
  })
})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
var flipSection
A variable we established to store our array. This is variable holds all of our add-on classes and where they should they should be added. You can name this variable anything you want
You can create multiple arrays to apply within the same Collection List. This theoretically makes it possible to achieve any style of layout structure within a single Collection List
classTarget
The class of the element that you want to add a new class to. If you want to add the '.cool' class to '.not-cool', '.not-cool' would be your class target.
classToAdd
The class that you want to add to your classTargetd . In our example in classTarget, the classToAdd would be '.cool'
classArray
Where we use our variable that holds array we created. In the example, this would be flipSection
frequency
The frequency of the classes being added to the list
A frequency of 1 means that add-on classes would be added to every item in the list, a frequency of 2 would add the add-on classes to every other item in the list, and a frequency of 4 would add the add-on classes to every 4th item in the list
start
Specify when the classes start being added to the Collection List
A start of 1 would start adding the add-on classes on the first item in the list, a start of 2 would start adding the add-on classes on the second item in the list, and a start of 4 would start adding the add-on classes on the 4th item in the list

Frequency and Start

You may customize when in the Collection List the addclasses component starts adding classes, as well as customize the iteration which classes are added to the Collection List (add a class to every nth child). This is why we have frequency and start.

Here is a handy visual explanation to the frequency and start options. In the following examples we are adding the class that changes item's background to solid with the designated frequency and starting place.

“2” as frequency, “2” as start. Every 2 items, we add the class. We start at item 2
“2” as frequency, “3” as start. Every 2 items, we add the class. We start at item 3
“4” as frequency, “6” as start. Every 4 items, we add the class. We start at item 6
“3” as frequency, “1” as start. Every 3 items, we add the class. We start at item 1
“0” as frequency, “3” as start. Every 0 items, we add the class (meaning we only add the class once). We start at item 3

Establish add-on classes

Give base classes add-on classes to establish their style change
Tell Webflow what '.reverse-flex' does and save that style somewhere safe in your project.
Anything goes
Single add-on classes, 5x add-on classes on one element, go for it. We can add any amount of classes to any amount of classes
Component #6

Nest

Simulate multiple nested Collections on a single page

Use cases

When you need more flexibility with nested Collections
More than 1 Nested Collection on a page
Instead of using native nested Collections, use Nest to simulate as many nested Collections as you'd like.

How to use it

IMPORTANT: You need to double enter your multi reference fields as a text field. If you have an item that has "Advertising" and "Marketing" as the selected as multi reference items, you will need a text field that lists those items out in plain text comma separated list. In this example, the text in this field would be "Advertising, Marketing"

Paste before </body> tag of the page you're working with.

<script>
// immediately/self invoked function. This function executes right away
(function() {
  // create a new Library instance and store it in a variable called "customBlogPosts"
  var customBlogPosts = new FsLibrary('.blog-posts-list')

  // run nest on our instance
  customBlogPosts.nest({
     textList: '.text-of-categories-list',  // plaintext comma separated list
     nestSource: '.nest-multi-reference',  // CMS list we are taking real tags from
     nestTarget: '.multi-ref-target'  // where we paste the items from nestSource
  })
})();
</script>
Copy code

Code explanation

customBlogPosts
The variable we created to store our Library instance. The name of the variable can be set to whatever you want.
textList
The class of the plain text list that holds our multi-reference information.
nestSource
The class of the hidden Collection List that holds our real multi reference content
nestTarget
The class of the div that we will put our real multi-reference into

HTML and class setup

Add 2 Collection Lists to the page. One list should be visible to the user. One list will be hidden
The visible list on the page is the list we define our new instance with. In this example, this is our.blog-posts-list. Inside this list we have our, .multi-ref-target and .text-of-categories-list classes.

The .text-of-categories-list is the plain text comma separated list of our multi-reference fields. The.multi-ref-target is our wrapper for our real multi-reference items.

The hidden Collection List is going to hold all of our real multi-reference items. This list gets a class on the List element. In this example, this is .nest-multi-reference.

The Nest component is going to find matches in our plain text list and items inside the .nest-multi-reference Collection List. When it finds a match, it will put the matched content inside our .multi-ref-target.

In this example, .nest-category-link items will be added to .multi-ref-target

Combos

Can

Filter + Sort

Combine + Filter

Combine + Sort

Combine + Filter + Sort

Combine + Filter + Sort + Add Classes

Nest + Filter

Nest + Load More

Nest + Combine + Filter + Sort

Known Limitations

Load More + Filter

Your filter will only filter items that are loaded on the page. Items that have not yet been loaded will not be filtered in results.

When you set a filter and then load more items, the newly loaded items won't be filtered based on the current filter selection. We're thinking of ways to implement this!

Load More + Sort

You can only sort through items that are loaded ton the page. Items that have not yet been loaded will not be sorted in results. Loading new items to the page will not sort them on load. Same concepts as above.

Load More + Add Classes

Only the original items loaded on the page will get the added classes

Known Can'ts

Load More + Combine

This does not work. If you are combining items, it’s intended that you want all of your items to show on the page. If you’re loading more items, it’s intended you don’t want all of your items to show on the page. Using them together breaks shit.

User feedback

Send us issues with Combos

Is a combo not working as expected? Tell us. There is no way we can test everything ourselves. The community has been excellent so far. Just 2 days after launch, we've already squashed 2 combo issues. An update will release soon.

License

Using the library is 100% free for personal and commercial use.

The use of F'in sweet CMS Library will always be free for all users.

You are strictly prohibited to replicate, edit, remix, redistribute, resell, 'duplicate and change a little', or make any type of modification to this library script file.

Contact Us

Request a feature or report a bug!

Thank you! Your message has been received!
Something went wrong while submitting the form

Support

Finsweet offers free support for the F'in sweet CMS Library.

Javascript support, errors fixes, customizations, and live chat are all included with this product, free of charge. All Finsweet products have free javascript service included.

Go to sweetjs.io to learn more.