Cautions

The freedom that Freighter provides naturally has a few cautions to be aware of. With so many properties that work together, it is easy to accidentally create a situation that is not intended.

Reserved IDs and Classnames

In order to make Freighter work, a number of custom HTML and CSS IDs and classnames are used internally. In order to prevent any conflicts, it is recommended that you do not use any of the following IDs or classnames in your HTML. If you are experiencing any odd behavior, check to make sure that you are not already using any of these in your own HTML.

Reserved IDs:

  • #freighter-carousel-container-*
  • #freighter-carousel-item-container-wrapper-*
  • #freighter-carousel-item-container-*
  • #freighter-carousel-item-*-*
  • #freighter-carousel-arrow-left-*
  • #freighter-carousel-arrow-right-*
* Note that the asterisk (*) in the above IDs will be replaced with some number, so both #freighter-carouse-item-2-1 and #freighter-carousel-item-4-3 are potentially unsafe IDs to use.

Reserved classes:

  • .freighter-carousel-container
  • .freighter-carousel-item-container-wrapper
  • .freighter-carousel-item-container
  • .freighter-carousel-item
  • .frieghter-carousel-item-dummy
  • .freighter-carousel-arrow-left
  • .freighter-carousel-arrow-right

Duplicate Carousel Items

As is discussed in the wrapping page of the documentation, there are a number of wrapping methods that cause carousel items to 'wrap' from end to end. In certain situations, such as when the carousel contains fewer items than the numItemsVisible property, empty spaces will be filled with duplicate items.

If your carousel is set up in a way that makes this possible, and elements that are children of the carousel items will also be duplicated, potentially duplicating IDs. Take the carousel below as an example. If you inspect the carousel items, you will notice that the id attribute of some are duplicated.

For the most part, this shouldn't cause any issue. If, however, you write code that assumes only one element in the DOM will have a given ID, this may cause that code to break. Use your best judgement when pairing a wrapping method with carousel items that have functionality dependent on their IDs.


Freighter and the DOM

When a Freighter carousel is constructed, more elements are created than just the container and children (this becomes more obvious when you see the number of reserved IDs and classnames that exist)! Feel free to inspect the carousel in your browser's developer tools to see some of these.

It is important to point out that you should not add or remove any styles, event listeners, or children from any of these elements. These are all maintained by Freighter, and changing them in any way risks breaking the carousel. If you are feeling brave, and feel as though you understand how something has been implemented, just be aware that you may end up breaking something down the line.


Changing Styles

One important design decision made was to ensure that elements created by you are not altered in any way: both the top-level carousel container

<div id="carousel-1" class="freighter-c"></div>

as well as all carousel items

<div class="ci"><p>1</p></div>

remain untouched, as indicated by a lack of inline styles. This gives the programmer (mostly) total freedom to style each of these components of the carousel as they wish. The only warning that is associated with this feature is to avoid styling relative to the carousel items or containers . Applying CSS styles that impact parents of the carousel items or children of the carousel container with selectors such as >, ~ or instances of has() may end up overriding essential styles to internal Freighter elements.

In general, it is advised to give carousel elements a common class for styling, and apply your CSS styles to the classes themselves rather than parents or children of elements.


Transition Timing Functions

Freighter provides you with the ability to select your own custom CSS transition timing functions. These can be as simple as linear or as complex as cubic-bezier(), but the more complex come with an important caution.

Internally, Freighter only inserts as many carousel items as necessary; if you create a carousel with 15 items but set numItemsVisible to 3, then the other 12 items are stored in memory until they should come into view. For this reason, some cubic-bezier() functions that go beyond the items visible on the screen may result in blank spots in the carousel. The code below demonstrates a dangerous carousel whose transition timing function goes beyond the visible items to an extreme degree.

const myCarousel = new Freighter(
  'myCarousel',
  'stretch-scale',
  'none', {
    numItemsVisible: 2,
    scrollBy: 1,
    itemSpacing: 15,
    transitionTimingFunction: "cubic-bezier(0.65, 0, 0.35, -5)",
    transitionDuration: 1500,
  }
);

Notice that with a function this extreme, at first the previous items show up properly. Scrolling from items 3 on demonstrates that only one previous item is added to either side when transitioning, which also happens to be the scrollBy value for this carousel.

In fact, below is a breakdown of how many carousel items are actually exist in the DOM at the stages of the carousel transition:

  • Before Transition: numItemsVisible carousel items loaded.
    • Only need to load those that are currently visible in the carousel.
  • During Transition: numItemsVisible + (2 * scrollBy) carousel items loaded.
    • scrollBy additional items are added to each side during a scroll in either direction.
  • After Transition: numItemsVisible carousel items loaded.
    • The extras are removed when the transition completes.

In the example above, then, we can only ever assume that 1 extra carousel item will be inserted into the carousel on either side during transitions. As long as the cubic-bezier() function does not expose more than one extra carousel item, this shouldn't be a problem.


Changing from wrap-smart to wrap-simple

Both of the wrapping methods ensure that there are never any empty spots in a carousel; if there normally would be with wrapping method none, they are filled with carousel items from the start of the container. Nothing new here.

wrap-smart, however, modifies the amount that will be scrolled in order to preserve the absolute ordering of the carousel items - an item with a lower index will never be shown after an item with a higher index. Again, this is all understood by the definition of the wrapping method.

There is one situation in which these rules are in contradiction: that is, when numItemsVisible is larger than the total number of carousel items, as shown below:

const myCarousel = new Freighter(
  'myCarousel',
  'stretch-scale',
  'wrap-simple', {
    numItemsVisible: 5,
    itemSpacing: 15,
  }
);

Clearly, the above carousel could not use wrap-smart, as the absolute ordering of the items would not be preserved. What happens, then, if you try to use this wrapping method in a situation like this? The carousel below is the result of such an attempt:

Looks the same, and if you try scrolling, you will see it behaves the screen. This is because the carousel has been converted to use wrap-simple! Check the console to see the warning message that displays when this occurs; it looks something like this:

Carousel ID "carousel-4": Cannot allow smart wrapping if the carousel has fewer items than items visible. Setting wrapping method to 'wrap-simple'.

This may occur with other combinations of carousel properties. What if you initially keep numItemsVisible less than the total number of carousel items, but one of these changes later? Suppose you remove carousel items, or decrease the numItemsVisible, or use the resizing method stretch-populate which can increase the numItemsVisible? In all of these cases (and any other you can think of), when it is detected that the absolute ordering of carousel items cannot be maintained, the carousel is automatically converted to use wrap-simple

Check out the following example. After you remove an item from the carousel, you will notice that an absolute order cannot be maintained, so the wrapping method switches and a warning is output to the console.

As long as you are cautious about changing the numItemsVisible property, this should not be a problem.