Remix adding resources with the link tag

Chris Bongers - May 7 '22 - - Dev Community

The link tag is a way to add specific resources to your webpage, the most commonly known one is stylesheets.

We can load them in plain HTML by using the link tag like this:

<link rel="stylesheet" href="assets/styles.css" />
Enter fullscreen mode Exit fullscreen mode

Another use-case is to load the site's icon like the favicon with this link element.

And last but not least, it's not limited to this. It can be used to preload some assets!

Yes, the link API is pretty sick and powerful.

Using the link element in Remix

If you followed along with my articles on Remix, you used one of their fantastic starter where the root.tsx file already uses the links element.

In Remix, you can add links to an array like this:

import tailwindStylesheetUrl from './styles/tailwind.css';

export const links: LinksFunction = () => {
  return [{ rel: 'stylesheet', href: tailwindStylesheetUrl }];
};
Enter fullscreen mode Exit fullscreen mode

This LinksFunctions can be invoked from every route file you create, so you can also inject very specific stylesheets on different pages.

Inside our render we then simply have to inject a property like this:

export default function App() {
  return (
    <html>
    <head>
        ...
      <Links />
    </head>
    ...
  );
}
Enter fullscreen mode Exit fullscreen mode

If you import this in your root, you don't specifically have to import it on other pages.

Using specific stylesheets elsewhere

A different single page has some charts that need the CSS stylesheet.
This page can be about.tsx, for instance. If we open that up, we can add a links function there like this:

import chartStyles from '../styles/charts.css';

export const links: LinksFunction = () => {
  return [
    {
      rel: 'stylesheet',
      href: chartStyles,
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

And now, if we open the about page, we can see our original tailwind stylesheet and this chart stylesheet injected.

Types of links

As mentioned, we have the option to add quite a few different types of links.
Let's take a look at some examples.

Favicon links

First up, a favicon. The icon uses in your web browser.

export const links: LinksFunction = () => {
  return [
    {
      rel: 'icon',
      href: '/favicon.png',
      type: 'image/png',
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

Local links

Then we already saw we could add a local stylesheet. The good thing to note is the import we use.
This import is essential to note as it will make sure Remix will fingerprint this file for production caching. (Making it a unique URL)

import chartStyles from '../styles/charts.css';

export const links: LinksFunction = () => {
  return [
    {
      rel: 'stylesheet',
      href: chartStyles,
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

External links

We can also load external links by simply passing the full URL to the href property.

export const links: LinksFunction = () => {
  return [
    {
      rel: 'stylesheet',
      href: 'https://example.com/some/styles.css',
      crossOrigin: 'true',
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

Prefetch images

As mentioned, the links API is very powerful, and it can even be used to prefetch images, for instance.

export const links: LinksFunction = () => {
  return [
    {
      rel: 'prefetch',
      as: 'image',
      href: '/img/bunny.jpg',
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

Conditional prefetching

The cool part about prefetching is that you can specify media queries for this prefetch.

LEt's say we only want to prefetch this image on bigger screens.

export const links: LinksFunction = () => {
  return [
    {
      rel: 'prefetch',
      as: 'image',
      href: '/img/bunny.jpg',
      media: '(min-width: 1000px)',
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

Conditional adding stylesheets

We can also use the above media technique to add stylesheets only on certain queries:

export const links: LinksFunction = () => {
  return [
    {
      rel: 'stylesheet',
      href: printStyles,
      media: 'print',
    },
    {
      rel: 'stylesheet',
      href: highResStyles,
      media: 'screen and (min-resolution: 300dpi)',
    },
  ];
};
Enter fullscreen mode Exit fullscreen mode

And that's it. The links element in Remix is super powerful, as it's built on the native links API.
I love that Remix takes such a promising premise of using what is already there and enhancing the browser capabilities.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .