@alangdm/block-link

A simple and super lightweight web component to create block links.

Usage no npm install needed!

<script type="module">
  import alangdmBlockLink from 'https://cdn.skypack.dev/@alangdm/block-link';
</script>

README

edit-in-WebComponents.dev npm minzipped size

<block-link>

Demo

A simple and super lightweight web component to create block links.

<script
  src="https://unpkg.com/@alangdm/block-link?module"
  type="module"
></script>

<block-link main-link="h2 a">
  <small><a href="#date">Date: 2020/01/01</a></small>
  <h2><a href="#header">Header</a></h2>
  <p>Some content</p>
  <footer><a href="#footer">Footer link</a></footer>
</block-link>

Why Should You Use This?

Have you ever set a link on a whole section of your web app like this?

<a href="/some-link">
  <div>
    Some content maybe with an image
    <img src="/some-image.png" />
  </div>
</a>

If you have, you probably have noticed that while this is super simple, it has a couple of issues:

  1. You can't select the text inside this div
  2. The accessibility is bad, keyboard navigation and screen readers don't work well with this

And even if you want to solve this either with pure HTML/CSS or adding some JS you might new problems like:

  1. Links added to children of the section might not work
  2. Using this for many parts of your app might get confusing and hard to maintain

This component solves all those problems and you can use it like you would use a plain old <div>.

How it Works

This component's code is mostly an adapted version of the code in the article "Block Links: The Search for a Perfect Solution" by Vikas Parashar (@vicode_in).

There are only slight differences in the core behavior of both implementations so if you want more insight on the thought that went into this code to prevent the problems mentioned above please give Vikas's article a read.

Getting Started

Install from npm

npm i @alangdm/block-link

Import the component in your JS files

import "@alangdm/block-link";

Add from a CDN

You can use a CDN like unpkg or Pika CDN too

In your HTML files

<!-- example from unpkg -->
<script
  src="https://unpkg.com/@alangdm/block-link?module"
  type="module"
></script>

Or in your JS files

import "https://unpkg.com/@alangdm/block-link?module";

Use in Your Code

Basically, just use it as if it was a <div>, all the magic will happen automatically! 🎉

<block-link>
  <h2><a href="#header">Main Link</a></h2>
  <p>
    Some Text
  </p>
  <footer><a href="#footer">Footer link</a></footer>
</block-link>

By default, the first <a> element inside the block-link component will be used as the link that gets triggered when a user clicks on any place that's not another link.

Customizing the Main Link

You can add the main-link (or mainlink) attribute to customize which element is used as the main link.

The value has to be a selector relative to the parent <block-link> that can be used to identify the <a> that will be your main link.

<block-link main-link=".main-link">
  <h2><a href="#header">This won't be the main link</a></h2>
  <p>
    Some text
  </p>
  <footer>
    <a class="main-link" href="#footer">This will be the main link</a>
  </footer>
</block-link>

In this case we used the .main-link class selector to identify our main link, but we could have also used footer>a or even a[href="#footer"]. Any selector works as long as it serves as a unique identifier for the link.

Nested <block-link>s

You can use <block-link>s inside of other <block-link>s, they can even be the main link.

<block-link main-link=".child">
  <block-link class="child" main-link="#link">
    <img src="/some_image.png" />
    <a href="#main_link" id="link">This will end up being the main link</a>
  </block-link>
  <p>Some other content. It might have <a href="#other">other links</a></p>
</block-link>

Styling

This component's only style is display: block; but you can customize both the component and its children behave with plain CSS.

block-link {
  width: 200px;
  height: 200px;
  border: 1px solid black;
}

block-link h2,
block-link a {
  color: purple;
}

block-link a {
  text-decoration: none;
}

This would look something like this in action (Go here if you can't see this properly ):

import "./index.js";

Interactive Demo

This will only work if you're viewing it at the demo/docs site.

Browser Support

This component works as-is on all evergreen browsers (Chrome, Safari, Edge, Firefox). 💪

This component doesn't support any IE variation, however, due to it's nature, it will degrade gracefully on IE so that the markup and styles display properly just without the block link behavior, for example, clicking on links will work but clicking on the rest of the component won't.

Great Articles on This Topic

Created with WebComponents.dev