<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Skypack</title>
    <description>The latest articles on Forem by Skypack (@skypack).</description>
    <link>https://forem.com/skypack</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3697%2Fbda4770f-77d9-4cdb-8340-f6eaf268b666.png</url>
      <title>Forem: Skypack</title>
      <link>https://forem.com/skypack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/skypack"/>
    <language>en</language>
    <item>
      <title>The best classless CSS frameworks in 2021</title>
      <dc:creator>Melissa McEwen</dc:creator>
      <pubDate>Tue, 09 Mar 2021 00:13:36 +0000</pubDate>
      <link>https://forem.com/skypack/the-best-classless-css-frameworks-in-2021-427a</link>
      <guid>https://forem.com/skypack/the-best-classless-css-frameworks-in-2021-427a</guid>
      <description>&lt;p&gt;Ever need style for some plain HTML? Then classless CSS frameworks are for you. I started using these when working on code examples for our &lt;a href="https://www.skypack.dev/blog/2021/02/the-best-javascript-date-libraries/" rel="noopener noreferrer"&gt;Best Date Libraries&lt;/a&gt; post. The plain HTML examples looked distractingly ugly, but writing I didn't want to write any CSS. I found &lt;a href="https://github.com/oxalorg/sakura" rel="noopener noreferrer"&gt;Sakura&lt;/a&gt;, a classless CSS framework. With just one CSS file my examples looked far more polished. And I didn't have to change the HTML at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhhyvo3ofp1jra1n64x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhhyvo3ofp1jra1n64x2.png" alt="before and after of applying Sakura classless CSS" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a classless CSS framework?
&lt;/h2&gt;

&lt;p&gt;Classless CSS differs from other types of CSS frameworks that target classes. For example, with &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt; (the most popular traditional CSS framework) you need to add &lt;code&gt;class="blockquote"&lt;/code&gt; to your &lt;code&gt;blockquote&lt;/code&gt;s to style them. Or &lt;a href="https://jgthms.com/wysiwyg.css/" rel="noopener noreferrer"&gt;WYSIWYG.css&lt;/a&gt;, a "class-light" CSS framework. WYSIWYG.css targets basic HTML elements, but only within a container with &lt;code&gt;class="wysiwyg"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8lyiszxhbmvivdoxmq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8lyiszxhbmvivdoxmq2.png" alt="Shows a little character with an html face and a classless framework hat saying " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who are classless CSS frameworks for?
&lt;/h2&gt;

&lt;p&gt;Classless CSS frameworks are ideal for demos, proofs of concept, minimalist sites, and code examples. &lt;/p&gt;

&lt;p&gt;Beyond that, their lack of precision limits design options and can override other CSS, making a larger site design look weird. Furthermore they don't offer much contextual flexibility. For example let's say you want to have headers look different when used on a sidebar vs. the body of a blog post. It's also almost impossible to have a layout beyond a basic single column without using classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing classless CSS frameworks
&lt;/h2&gt;

&lt;p&gt;We picked &lt;a href="https://codepen.io/collection/XyWVxw?cursor=ZD0xJm89MSZwPTEmdj0z" rel="noopener noreferrer"&gt;eleven classless CSS frameworks to test in Codepen&lt;/a&gt;. Want to see what they look like when applied to the same page? Toggle them in our Classless CSS Tester Codepen:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/WNoweNg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Our favorite: &lt;a href="https://github.com/oxalorg/sakura" rel="noopener noreferrer"&gt;Sakura&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I ended up picking &lt;a href="https://codepen.io/melissamcewen/pen/vYXMvaX" rel="noopener noreferrer"&gt;Sakura&lt;/a&gt; for use in examples in Codepen. Sakura covers most HTML elements I use in examples such as headers. Most importantly, Sakura makes HTML look tidy and readable, but isn't distracting.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/vYXMvaX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  For prototyping: &lt;a href="https://andybrewer.github.io/mvp/" rel="noopener noreferrer"&gt;MVP.css&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you're building a prototype, &lt;a href="https://codepen.io/melissamcewen/pen/mdrYWEJ" rel="noopener noreferrer"&gt;MVP.css&lt;/a&gt; is a great choice. MVP.css allows you to construct basic user interfaces with plain HTML. If you're at a hackathon or just hacking a side project, check this one out:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/mdrYWEJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  For bloggers: &lt;a href="https://holidaycss.js.org/" rel="noopener noreferrer"&gt;holiday.css&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you're building a simple blog and want basic style, &lt;a href="https://codepen.io/melissamcewen/pen/qBawGwP" rel="noopener noreferrer"&gt;holiday.css&lt;/a&gt; looks clean and styles the semantic elements commonly used in writing. Plus it has a cool dark mode!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/qBawGwP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What to look for in a classless CSS framework
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Readability
&lt;/h3&gt;

&lt;p&gt;Ideally, a classless CSS framework should make text much more readable. Some things to look for are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spacing: Does the framework use spacing to improve readability and convey hierarchy?&lt;/li&gt;
&lt;li&gt;Fonts: Does the framework use fonts designed for the web? For example &lt;a href="https://designforhackers.com/blog/garamond/" rel="noopener noreferrer"&gt;Why You Don’t Use Garamond on The Web&lt;/a&gt; explains why some fonts aren't suited for use on websites. Are the font sizes readable and do they have a clear hierarchy? That can be complicated to judge but I like the pointers laid out in &lt;a href="https://learnui.design/blog/mobile-desktop-website-font-size-guidelines.html" rel="noopener noreferrer"&gt;The Responsive Website Font Size Guidelines
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Color contrast: Color can make a difference in how legible text is. Check out the accessibility section for more on this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Coverage
&lt;/h3&gt;

&lt;p&gt;It's worth thinking about what HTML elements you want to style. Not all frameworks style the same elements. When I write blog posts I like to use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;&lt;/a&gt; element for tips and other tangential information. Many classless CSS frameworks do not style asides, which makes them look like part of a paragraph. On the flip side, there may be elements you do not want to style. MVP.css styles &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; elements which might be confusing on a blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Size
&lt;/h3&gt;

&lt;p&gt;Most classless CSS frameworks are small, ranging from 1.3 to 5.1 kb. The exception is those that use custom fonts. Classless css frameworks that use &lt;a class="mentioned-user" href="https://dev.to/import"&gt;@import&lt;/a&gt; for custom fonts are usually around 200-600kb. You have to decide whether those fonts are worth their size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theming
&lt;/h3&gt;

&lt;p&gt;A classless CSS framework can be as simple as a single CSS file, but others use tools like SASS that output CSS as part of a build process. The advantage of the more complex tool chain is the ability to "theme" the final output. For example, with Sakura you can create your own theme by changing variables in a SASS file. &lt;a href="https://holidaycss.js.org/" rel="noopener noreferrer"&gt;Holiday.css&lt;/a&gt; has both light and dark modes and switches based on &lt;a href="https://css-tricks.com/a-complete-guide-to-dark-mode-on-the-web/" rel="noopener noreferrer"&gt;&lt;code&gt;prefers-color-scheme&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility
&lt;/h3&gt;

&lt;p&gt;Is CSS really part of accessibility? Definitely! Let's take the humble &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element for example. If only styled with color, colorblind users may not be able to distinguish links from regular text. WebAIM's &lt;a href="https://webaim.org/techniques/hypertext/link_text#uninformative" rel="noopener noreferrer"&gt;Links and Hypertext guidance&lt;/a&gt; recommends styling links with an underline. And if links aren't underlined, have higher contrast and hover effects. For further reading on this topic see the WebAIM &lt;a href="https://webaim.org/articles/contrast/" rel="noopener noreferrer"&gt;Contrast and Color Accessibility guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some other common CSS accessibility issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Color contrast is too low — for example light blue text against a slightly less light blue background.&lt;/li&gt;
&lt;li&gt;User interface elements difficult to use — such as buttons that are too tiny to click.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Style
&lt;/h3&gt;

&lt;p&gt;Do you want to go for a minimal look or a more stylish sparkle ✨? Most classless CSS frameworks are minimalist. But there are a few with a distinctive style like &lt;a href="https://codepen.io/melissamcewen/pen/poEmeea" rel="noopener noreferrer"&gt;Tufte.css&lt;/a&gt;, based on the work of data visualization pioneer Edward Tufte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://alistapart.com/article/meaningful-css-style-like-you-mean-it/" rel="noopener noreferrer"&gt;Meaningful CSS: Style Like You Mean It&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dbohdan/classless-css" rel="noopener noreferrer"&gt;dbohdan/classless-css: A list of classless CSS themes/frameworks with screenshots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/troxler/awesome-css-frameworks" rel="noopener noreferrer"&gt;troxler-awesome-css-frameworks: List of awesome CSS frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/no-class-css-frameworks/" rel="noopener noreferrer"&gt;No-Class CSS Frameworks | CSS-Tricks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cssbed.com/" rel="noopener noreferrer"&gt;CSS Bed: This is a collection of classless CSS themes to use as starting points in web development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dohliam.github.io/dropin-minimal-css/" rel="noopener noreferrer"&gt;drop-in Minimal CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alexandersandberg.github.io/html5-elements-tester/" rel="noopener noreferrer"&gt;HTML5 elements tester: preview popular CSS resets and frameworks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The best JavaScript date libraries in 2021</title>
      <dc:creator>Melissa McEwen</dc:creator>
      <pubDate>Tue, 16 Feb 2021 15:28:33 +0000</pubDate>
      <link>https://forem.com/skypack/the-best-javascript-date-libraries-in-2021-19mm</link>
      <guid>https://forem.com/skypack/the-best-javascript-date-libraries-in-2021-19mm</guid>
      <description>&lt;p&gt;Wrangling dates and times in JavaScript can be a headache. JavaScript date libraries provide user-friendly APIs and useful utilities that alleviate some of that pain. But with so many options how do you pick the best one? In this post we delve into the world of JavaScript date libraries to help you choose. Our top pick, &lt;strong&gt;date-fns&lt;/strong&gt;, delivers the best feature set combined with an elegant modular architecture.&lt;/p&gt;

&lt;h2 id="our-picks"&gt;Our picks&lt;/h2&gt;

&lt;h3 id="best-overall-date-fns"&gt;Best overall: &lt;a href="https://www.skypack.dev/view/date-fns" rel="noopener noreferrer"&gt;date-fns&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;date-fns&lt;/strong&gt; offers great documentation, functional architecture, and utilities that handle almost any task you can think of. If dates are a critical concern for your JavaScript application, use &lt;strong&gt;date-fns.&lt;/strong&gt; Each feature has clear documentation written in ESM (ES Modules) for the browser. Logical and consistent function names encourage readable code. A modular architecture allows build tools to trim away unused code for a slimmer final build.&lt;/p&gt;

&lt;h3 id="best-for-time-zones-luxon"&gt;Best for time zones: &lt;a href="https://www.skypack.dev/view/luxon" rel="noopener noreferrer"&gt;Luxon&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If time zones or localization are your primary concern, we recommend &lt;strong&gt;Luxon&lt;/strong&gt;. &lt;strong&gt;Luxon&lt;/strong&gt; leverages JavaScript's &lt;code&gt;Intl&lt;/code&gt; for speed and slimness while providing what &lt;code&gt;Intl&lt;/code&gt; doesn't: an immutable user-friendly API. Concise, well-written documentation eases the learning curve for getting started. &lt;/p&gt;

&lt;h3 id="best-minimalist-option-dayjs"&gt;Best minimalist option: &lt;a href="https://www.skypack.dev/view/dayjs" rel="noopener noreferrer"&gt;Day.js&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;For basic handling of dates, &lt;strong&gt;Day.js&lt;/strong&gt; is a minimalist library that offers an excellent API without much overhead. While &lt;strong&gt;Day.js&lt;/strong&gt; has fewer features than &lt;strong&gt;Luxon&lt;/strong&gt; or &lt;strong&gt;date-fns&lt;/strong&gt;, it's much smaller in size. &lt;/p&gt;

&lt;h2&gt;The Research&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When to use a JavaScript date library&lt;/li&gt;
&lt;li&gt;Our previous pick: Moment.js&lt;/li&gt;
&lt;li&gt;How we picked&lt;/li&gt;
&lt;li&gt;
Our picks in detail
&lt;ul&gt;
&lt;li&gt;Date-fns&lt;/li&gt;
&lt;li&gt;Day.js&lt;/li&gt;
&lt;li&gt;Luxon&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Other JavaScript date libraries&lt;/li&gt;

&lt;li&gt;Useful Resources&lt;/li&gt;

&lt;/ul&gt;

&lt;h2 id="when-to-use-a-datetime-package"&gt;When to use a JavaScript date library&lt;/h2&gt;

&lt;p&gt;Why not just use JavaScript's built-in &lt;strong&gt;Date&lt;/strong&gt; object? A good JavaScript date library provides a clear advantage over JavaScript's &lt;strong&gt;Date&lt;/strong&gt; in several ways: immutability, parsing, and time zones. In addition, JavaScript date libraries offer useful utilities for date manipulation and formatting, which can save developers time and energy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ Maggie Pint's blog post &lt;a href="https://maggiepint.com/2017/04/09/fixing-javascript-date-getting-started/" rel="noopener noreferrer"&gt;Fixing JavaScript Date&lt;/a&gt; describes how Javascript's &lt;strong&gt;Date&lt;/strong&gt; was based on a &lt;em&gt;Java&lt;/em&gt; (nope, not a typo) API from the 1990s. That Java API is long gone from Java but its problems live on in JavaScript's &lt;strong&gt;Date&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;JavaScript's &lt;strong&gt;Date&lt;/strong&gt; is mutable, which can lead to unintentional bugs. Let's say you create a &lt;strong&gt;Date&lt;/strong&gt; object named &lt;code&gt;currentTime&lt;/code&gt;. You display it on top of the website. Another developer comes in and wants to create a widget that displays next weeks events. They use &lt;code&gt;currentTime.setDate(currentTime.getDate() + 7)&lt;/code&gt; at the top to the widget to display next week's date. However it also changes the date in the header! Oops. With an immutable date library, adding a week would create a new instance so the original would not change.&lt;/p&gt;

&lt;p&gt;While &lt;strong&gt;Date&lt;/strong&gt; has a &lt;code&gt;parse&lt;/code&gt; method, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date" rel="noopener noreferrer"&gt;MDN documentation for &lt;strong&gt;Date&lt;/strong&gt;'s &lt;code&gt;dateString&lt;/code&gt; notes&lt;/a&gt; that usage is "strongly discouraged." An excellent answer in the Stack Exchange question &lt;a href="https://stackoverflow.com/a/20463521" rel="noopener noreferrer"&gt;Why does Date.parse give incorrect results?&lt;/a&gt; describes in detail differences in formatting standards and browsers lead to inconsistent and unreliable results. If you need to parse, a date library is a must.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;a href="https://zachholman.com/talk/utc-is-enough-for-everyone-right" rel="noopener noreferrer"&gt;UTC is enough for everyone..right?&lt;/a&gt; is an incredible interactive presentation by Zach Holman on how dates work in programming&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Time zones are another major frustration. &lt;strong&gt;Date&lt;/strong&gt; in the browser always represents the local system date stored as milliseconds since January 1st, 1970 in UTC. A &lt;strong&gt;Date&lt;/strong&gt; can rendered as a &lt;code&gt;string&lt;/code&gt; in a different time zone using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl" rel="noopener noreferrer"&gt;&lt;strong&gt;Intl&lt;/strong&gt;&lt;/a&gt;, but the &lt;strong&gt;Date&lt;/strong&gt; itself is always the local system time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Date&lt;/strong&gt; also lacks utilities for common tasks like creating human-readable relative dates. Using library utilities for such tasks can save a lot of time.&lt;/p&gt;
 

&lt;blockquote&gt;

&lt;p&gt;ℹ️ TC39, the major JavaScript standard's committee, is working on a new modern API called Temporal (&lt;a href="https://github.com/tc39/proposal-temporal" rel="noopener noreferrer"&gt;see the proposal here&lt;/a&gt;) that solves all of the above issues. &lt;a href="https://medium.com/better-programming/the-future-of-date-and-time-in-javascript-e1772c7976c" rel="noopener noreferrer"&gt;The Future of Date and Time in JavaScript&lt;/a&gt; by Christofer Eliasson is an excellent read of the history behind Temporal and what it means for JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the meantime, be aware of the limitations of &lt;strong&gt;Date&lt;/strong&gt; and use a library when you need one.&lt;/p&gt;

&lt;h2 id="our-previous-pick-momentjs"&gt;Our previous pick: Moment.js&lt;/h2&gt;

&lt;p&gt;For a long time &lt;strong&gt;Moment.js&lt;/strong&gt; was king of the JavaScript date libraries, but in 2020 &lt;strong&gt;Moment.js&lt;/strong&gt;'s maintainers published a &lt;a href="https://momentjs.com/docs/#/-project-status" rel="noopener noreferrer"&gt;Project Status&lt;/a&gt; announcing they consider Moment.js a legacy project. &lt;/p&gt;

&lt;p&gt;The maintainers argued that there was no way to refactor &lt;strong&gt;Moment.js&lt;/strong&gt; to meet the demands of modern JavaScript development such as immutability and tree shaking. Lighthouse (Chrome's built-in auditing tool) warns against using Moment because of its large size (329 kb).&lt;/p&gt;

&lt;p&gt;For these reasons, we do not include it as one of our recommended picks. If you are looking for a replacement to &lt;strong&gt;Moment.js&lt;/strong&gt; that closely matches its API, try &lt;strong&gt;Day.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id="how-we-picked"&gt;How we picked&lt;/h2&gt;

&lt;p&gt;We looked at data from &lt;a href="https://www.skypack.dev/" rel="noopener noreferrer"&gt;Skypack&lt;/a&gt; and &lt;a href="https://www.npmtrends.com/" rel="noopener noreferrer"&gt;NPM trends&lt;/a&gt; to identity the most popular and trending libraries and evaluated them against these core criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser-friendly&lt;/strong&gt;: We evaluated JavaScript date libraries for use directly by the browser rather than the Node.js backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great documentation&lt;/strong&gt;: Users look to this to implement the library correctly. We looked at the parts the facilitate this process: organization, search, examples, and the individual pages relating to the methods we tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity + Tree shaking&lt;/strong&gt;: Modular architecture allows you to shrink your library size by "tree-shaking" out any library code you're not using. Common build tools capable of tree-shaking include &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;, &lt;a href="https://snowpack.dev/" rel="noopener noreferrer"&gt;Snowpack&lt;/a&gt; and &lt;a href="https://rollupjs.org" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features&lt;/strong&gt;: Feature-richness was just one factor. We also considered whether a library was especially good at certain tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Measuring performance gives us a clue at how fast each library performs common operations. This usually isn't noticeable but in large, complex apps can cause lag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size&lt;/strong&gt;: One of the biggest problems people had with &lt;strong&gt;Moment.js&lt;/strong&gt; was size. A large library can substantially increase page load times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-bug features&lt;/strong&gt;: Immutability, readability, and informative error messages can help prevent bugs. When code is readable, you can learn a lot about what it does by reading it. Format, syntax, and naming conventions can make all the difference in readability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="how-we-tested"&gt;How we tested&lt;/h3&gt;

&lt;p&gt;When evaluating each library we made a CodePen using Skypack. We attempted to pick out common use cases that illustrate differences between libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rendering the current date &amp;amp; time&lt;/li&gt;
&lt;li&gt;Rendering the current date using a custom format&lt;/li&gt;
&lt;li&gt;Modifying a date to add/remove time&lt;/li&gt;
&lt;li&gt;Working with timezones&lt;/li&gt;
&lt;li&gt;Parsing arbitrary date strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First we implemented these cases using JavaScript's &lt;strong&gt;Date:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/NWRMoLm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We wrote up examples for performance testing on &lt;a href="https://perf.link/" rel="noopener noreferrer"&gt;perf.link&lt;/a&gt; and all of the tests and code are available in the &lt;a href="https://github.com/melissamcewen/date-time-perf-examples/" rel="noopener noreferrer"&gt;Date/time performance examples GitHub repository&lt;/a&gt;. If you have a specific use-case, you can modify one of the provided examples. JavaScript date libraries contain hundreds of methods and features that we couldn't test them all. Instead, we opted to test the same methods demonstrated in our Codepens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.skypack.dev%2Fblog%2Fwp-content%2Fuploads%2F2021%2F02%2Ftesting-performance-perf-link-skypack-javascript-date-library-1024x559.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.skypack.dev%2Fblog%2Fwp-content%2Fuploads%2F2021%2F02%2Ftesting-performance-perf-link-skypack-javascript-date-library-1024x559.jpg" alt="A code block imports all the tested libraries via Skypack, then there are four blocks showing code for adding a week to a date using each JavaScript date library. The results are 1,990 ops/s Luxon, 25,495 ops/s Day.js, 817,780 ops/s JavaScript native date, 217,296 ops/s date-fns" width="800" height="436"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/melissamcewen/pen/YzGMyyd" rel="noopener noreferrer"&gt;A chart of the performance data is also available on CodePen&lt;/a&gt;. The data  doesn't indicate a clear advantage for any one library. Each JavaScript date library implements different features differently, so that's not surprising.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⏱ For other performance comparisons see&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://inventi.studio/en/blog/why-you-shouldnt-use-moment-js" rel="noopener noreferrer"&gt;Why you shouldn't use Moment.js...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/you-dont-need/You-Dont-Need-Momentjs" rel="noopener noreferrer"&gt;You don't (may not) need Moment.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The sizes listed on each review are based on loading via the Skypack CDN. If you're using a build tool to tree-shake and the library is tree-shakable (like &lt;strong&gt;date-fns&lt;/strong&gt;), the size will depend on what parts you use. For evaluating libraries with tree-shaking we recommend &lt;a href="https://bundlephobia.com/" rel="noopener noreferrer"&gt;Bundlephobia.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A caveat to our testing is we did not consider back-end &lt;code&gt;Node.js&lt;/code&gt; use. Many JavaScript date libraries rely on browser APIs so may not work correctly on the back-end.&lt;/p&gt;

&lt;h4 id="other-cases-to-test"&gt;Other cases to test&lt;/h4&gt;

&lt;p&gt;Depending on your needs there are lots of other tests you could do. If you'd like to test other features not covered here, you can make changes to any of the examples in our embedded Codepens or &lt;a href="https://codepen.io/collection/DKYbjR" rel="noopener noreferrer"&gt;CodePen date collection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it let us know if we have an invalid date when we pass in invalid items? For example moment(undefined) behaves like moment() and doesn't output an error, which could lead to bugs.&lt;/li&gt;
&lt;li&gt;How well does it handle different languages and locales?&lt;/li&gt;
&lt;li&gt;Can it render relative dates (like "4 days ago")? Can it do this in different languages?&lt;/li&gt;
&lt;li&gt;Does it work in older browsers?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="our-picks-in-detail"&gt;Our picks in detail&lt;/h2&gt;

&lt;h3 id="date-fns"&gt;&lt;a href="https://www.skypack.dev/view/date-fns" rel="noopener noreferrer"&gt;Date-fns&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Size: 58.9 kb (tree-shakable)&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/bGwjaGV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;date-fns&lt;/strong&gt; is a pleasure to use, offering all the benefits of a modular architecture and covering almost any date use case. Our example shows the power of good naming and syntax in conveying information. Code like &lt;code&gt;add(now, {days: 7})&lt;/code&gt; is straightforward to understand even if you're unfamiliar with &lt;strong&gt;date-fns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To get the most out of &lt;strong&gt;date-fns'&lt;/strong&gt;s modular architecture, use a tree-shaking build tool (see our criteria section) and import only the features you need:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import { format, add, getHours, parse } from "https://cdn.skypack.dev/date-fns@2.16.1";
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the example above, a tree-shaking build tool would remove all code from &lt;strong&gt;date-fns&lt;/strong&gt; that's not used in &lt;code&gt;format&lt;/code&gt;, &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;getHours&lt;/code&gt;, or &lt;code&gt;parse&lt;/code&gt;. The final build would be much slimmer. Still at 58.9kb for the whole package, it's not giant in the first place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;date-fns&lt;/strong&gt; doesn't package a browser build for NPM (&lt;a href="https://github.com/date-fns/date-fns/issues/1780" rel="noopener noreferrer"&gt;see the related GitHub issue&lt;/a&gt;) and therefore only works on CDNs that transform for the browser like &lt;a href="https://www.skypack.dev/" rel="noopener noreferrer"&gt;Skypack&lt;/a&gt; and &lt;a href="https://www.jsdelivr.com/esm" rel="noopener noreferrer"&gt;ESM.run&lt;/a&gt;. However, documentation has examples labeled for the browser as both ESM(ES Modules) and ES2015. This ensures developers don't get confused trying to run &lt;code&gt;Node.js&lt;/code&gt; backend code in the browser.&lt;/p&gt;

&lt;h4 id="limitations"&gt;Limitations&lt;/h4&gt;

&lt;p&gt;Although we liked almost everything about &lt;strong&gt;date-fns&lt;/strong&gt;, it is not for everyone. For starters, &lt;strong&gt;date-fns&lt;/strong&gt; seems geared towards experienced developers working with a professional tool chain. Working without a build tool, the tree-shaking advantage disappears.&lt;/p&gt;

&lt;p&gt;Note that our CodePen example starts with a &lt;code&gt;const now = new Date()&lt;/code&gt;, which is the default JavaScript &lt;strong&gt;Date&lt;/strong&gt; object. As noted in our &lt;strong&gt;Date&lt;/strong&gt; section a &lt;strong&gt;Date&lt;/strong&gt; is always the current system's time zone. &lt;strong&gt;date-fns&lt;/strong&gt; has a separate library for working with time zones using helper functions. We found the documentation and examples for these helper functions less consistent than the main &lt;strong&gt;date-fns&lt;/strong&gt;. Our resulting code is less readable than the rest of the examples. Our time-zone example for &lt;strong&gt;date-fns&lt;/strong&gt; is 4 lines of code, compared to 1 for &lt;strong&gt;Luxon&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Another quirk we encountered was if you Google "date-fns parse" the top results take you to the &lt;a href="https://date-fns.org/v2.0.0-alpha.9/docs/parse" rel="noopener noreferrer"&gt;v2.0.0-alpha docs for parse&lt;/a&gt;, which no longer work (the current version is 2.16). We found ourselves using Google because the documentation's built-in search seems to search only title and descriptions of sub-pages. The information architecture of the menu could also use improvement, as we would it overwhelmingly long. On occasion, a modal advertising "Get awesome JavaScript jobs to your email" covered the menu's bottom.&lt;/p&gt;

&lt;p&gt;The hardest part of implementing &lt;strong&gt;date-fns&lt;/strong&gt; Codepen examples was parsing, since they use different format tokens from other libraries. Furthermore, some tokens are not compatible with other tokens and the compatibility table is a Google doc that is hard to read.&lt;/p&gt;

&lt;h3 id="dayjs"&gt;&lt;a href="https://www.skypack.dev/view/dayjs" rel="noopener noreferrer"&gt;Day.js&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Size: 4kb&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/LYRJvNm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;Date&lt;/strong&gt; fulfills &lt;strong&gt;almost&lt;/strong&gt; all your needs but you don't want to deal with its downsides, &lt;strong&gt;Day.js&lt;/strong&gt; is a great choice. &lt;strong&gt;Day.js&lt;/strong&gt;'s small size makes it ideal for build-tool free environments like CodePen and plain JS/HTML/CSS projects. If you're forced to support older browsers, &lt;strong&gt;Day.js&lt;/strong&gt; 's &lt;a href="https://github.com/iamkun/dayjs" rel="noopener noreferrer"&gt;Readme&lt;/a&gt; says it supports IE as far back as IE 7, though we did not test these capabilities.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Day.js&lt;/strong&gt; documentation claims "If you use Moment.js, you already know how to use Day.js", which would make migrating easier. You can see direct comparisons at the excellent &lt;a href="https://github.com/you-dont-need/You-Dont-Need-Momentjs" rel="noopener noreferrer"&gt;You don't (may not) need Moment.js&lt;/a&gt;. The code in our example CodePen is readable with the exception of the parsing and time zone cases.&lt;/p&gt;

&lt;p&gt;A well-organized menu helped us find what we need in the &lt;strong&gt;Day.js&lt;/strong&gt; documentation. In addition the documentation search gives great results organized by type. We liked that most documentation pages have example code.&lt;/p&gt;

&lt;h4 id="limitations"&gt;Limitations&lt;/h4&gt;

&lt;p&gt;Like &lt;strong&gt;date-fns&lt;/strong&gt;, &lt;strong&gt;Day.js&lt;/strong&gt; builds on top of JavaScript's &lt;strong&gt;Date&lt;/strong&gt;, so time zone support requires another library. But unlike &lt;strong&gt;date-fns&lt;/strong&gt;, &lt;strong&gt;Day.js&lt;/strong&gt; relies on a plugin system that we did not find intuitive. You not only need to import the plugin but you also need to enable it by running &lt;code&gt;dayjs.extend(plugin_name)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is a stark contrast in our CodePen example between the time zone example and the other examples. The time zone example is much less readable and you'll also notice we commented it out. That's because it gave us incorrect results. It could be because our example time zone is an edge case or we did something wrong, but we attempted to follow the documentation. We recommend &lt;strong&gt;Luxon&lt;/strong&gt; instead if you need to deal with time zones.&lt;/p&gt;

&lt;p&gt;We encountered a few minor issues in the docs. The documentation does not contain any ESM (Es Modules) examples. This is especially apparent in &lt;a href="https://day.js.org/docs/en/plugin/loading-into-browser" rel="noopener noreferrer"&gt;the documentation for loading plugins in the browser&lt;/a&gt;, which recommends loading via script tag and then extending via the &lt;code&gt;window&lt;/code&gt; global. In general for readability and browser compatibility, we prefer to avoid globals.&lt;/p&gt;

&lt;p&gt;Unlike the other libraries you don't indicate a format with tokens when parsing. This worked fine in our CodePen but we wonder how correctly it would handle ambiguous formats. We felt &lt;a href="https://day.js.org/docs/en/parse/parse" rel="noopener noreferrer"&gt;the documentation could use more examples, specifically the parsing page&lt;/a&gt;. It took us a minute to realize parsing isn't its own method: you use &lt;code&gt;dayjs()&lt;/code&gt; and pass in a string. Unfortunately this syntax makes the code less understandable at a glance.&lt;/p&gt;

&lt;h3 id="luxon"&gt;&lt;a href="https://www.skypack.dev/view/luxon" rel="noopener noreferrer"&gt;Luxon&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Size: 29.5kb&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/melissamcewen/embed/wvzYeNN?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If time zones are high on your list of concerns, go with &lt;strong&gt;Luxon&lt;/strong&gt;. Dealing with time zones is never fun, so it's nice to use a library where it just works. Most date libraries don't have a built-in time-zone support because adding a time zone database is complex and adds a lot of weight to the final size. To get around this problem, &lt;strong&gt;Luxon&lt;/strong&gt; hacks into JavaScript's &lt;code&gt;Intl&lt;/code&gt; API, which most browsers support. It's the only JavaScript date library we evaluated that does not extend &lt;strong&gt;Date&lt;/strong&gt;, instead using its own &lt;code&gt;DateTime&lt;/code&gt; class. In our experience this makes working with time zones less bug-prone.&lt;/p&gt;

&lt;p&gt;Luxon's creator Isaac Cambron is a &lt;strong&gt;Moment.js&lt;/strong&gt; maintainer. In &lt;a href="https://moment.github.io/luxon/docs/manual/why.html" rel="noopener noreferrer"&gt;Why does Luxon exist&lt;/a&gt; he says "Luxon started because I had a bunch of ideas on how to improve Moment but kept finding Moment wasn't a good codebase to explore them with."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Luxon&lt;/strong&gt;'s documentation is divided up into a &lt;a href="https://moment.github.io/luxon/docs/manual" rel="noopener noreferrer"&gt;Manual&lt;/a&gt; and &lt;a href="https://moment.github.io/luxon/docs/identifiers.html" rel="noopener noreferrer"&gt;Reference&lt;/a&gt;. Since the more technical API documentation is in the &lt;a href="https://moment.github.io/luxon/docs/identifiers.html" rel="noopener noreferrer"&gt;Reference&lt;/a&gt;, the &lt;a href="https://moment.github.io/luxon/docs/manual" rel="noopener noreferrer"&gt;Manual&lt;/a&gt; is much more readable. Most importantly the &lt;a href="https://moment.github.io/luxon/docs/manual" rel="noopener noreferrer"&gt;Manual&lt;/a&gt; is well-written and organized into clear sections, with browser-friendly install instructions for ESM (ES Modules). The resulting code in our CodePen example is remarkably readable, particularly for the time zone case.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ "Can't we just get rid of time zones?" A common developer refrain, usually after dealing with a time zone related bug. &lt;a href="https://qntm.org/abolish" rel="noopener noreferrer"&gt;So You Want To Abolish Time Zones&lt;/a&gt; is a great read on why that's not a panacea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id="limitations"&gt;Limitations&lt;/h4&gt;

&lt;p&gt;We recommend &lt;strong&gt;date-fns&lt;/strong&gt; for date dependent applications because compared to &lt;strong&gt;Luxon&lt;/strong&gt; it has a larger feature set and is tree-shakable. If feature set is not a major concern, &lt;strong&gt;Day.js&lt;/strong&gt; is a better pick because it's ~7 times smaller than &lt;strong&gt;Luxon&lt;/strong&gt; (29.5kb for &lt;strong&gt;Luxon&lt;/strong&gt; vs. 4kb for &lt;strong&gt;Day.js&lt;/strong&gt;). Except for time zones, &lt;strong&gt;Luxon&lt;/strong&gt; doesn't offer a clear advantage.&lt;/p&gt;

&lt;p&gt;We noted above that &lt;strong&gt;Luxon&lt;/strong&gt; relies on &lt;code&gt;Intl&lt;/code&gt; and that &lt;strong&gt;most&lt;/strong&gt; browsers support it, but this doesn't include older browsers. &lt;a href="https://moment.github.io/luxon/docs/manual/matrix.html" rel="noopener noreferrer"&gt;A polyfill&lt;/a&gt; is available, but this will increase the complexity and size of using &lt;strong&gt;Luxon&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A minor quibble is &lt;strong&gt;Luxon&lt;/strong&gt;'s documentation search doesn't seem to index the entire text.&lt;/p&gt;

&lt;h2 id="other-datetime-packages"&gt;Other JavaScript date libraries&lt;/h2&gt;

&lt;p&gt;Here are two interesting JavaScript date libraries that we didn't have time to evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.skypack.dev/view/date-and-time" rel="noopener noreferrer"&gt;date-and-time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.skypack.dev/view/@js-joda/core" rel="noopener noreferrer"&gt;js-Joda&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="useful-resources"&gt;Useful Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://exploringjs.com/impatient-js/ch_dates.html" rel="noopener noreferrer"&gt;JavaScript for impatient programmers (ES2020 edition): Dates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zachholman.com/talk/utc-is-enough-for-everyone-right" rel="noopener noreferrer"&gt;UTC is Enough for Everyone, Right?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/better-programming/the-future-of-date-and-time-in-javascript-e1772c7976c" rel="noopener noreferrer"&gt;The Future of Date and Time in JavaScript | by Christofer Eliasson | Better Programming | Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/you-dont-need/You-Dont-Need-Momentjs" rel="noopener noreferrer"&gt;you-dont-need/You-Dont-Need-Momentjs: List of functions which you can use to replace moment.js + ESLint Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.logrocket.com/4-alternatives-to-moment-js-for-internationalizing-dates/" rel="noopener noreferrer"&gt;4 alternatives to Moment.js for internationalizing dates - LogRocket Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>codepen</category>
    </item>
  </channel>
</rss>
