# Fixing Table Double Borders in 
Screenshots

## Intro

I work at a startup company that develops several web applications. The app's code is older than my developer experience. If it is working, I rarely touch it. 😜 (Of course, I will change it if necessary.)

One of the apps I am developing has a function to capture a screen and save it as a jpeg. When I got a new task, which was implementing a table to the component, the style collapsed. 🙈 I need to figure out a way to keep it in style.

The original code uses [`html2canvas`](https://github.com/niklasvh/html2canvas) to make screenshots. As I said earlier, if it works, there is no need to change it. 🙏 To begin with, I start searching how to capture a table with `html2canvas`.

## TL;DR

<div data-node-type="callout">
<div data-node-type="callout-emoji">☝</div>
<div data-node-type="callout-text">Reduce overlapping borders for simple tables</div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">✌</div>
<div data-node-type="callout-text">Change library to <code>html-to-image</code></div>
</div>

## The Problem

This is a simple code for capturing an element using `html2canvas` and `file-saver`.

```typescript
import { saveAs } from "file-saver";
import html2canvas from "html2canvas";

const element = document.querySelector("#capture") as HTMLElement;
html2canvas(element, {
  scale: 1, // default is 2
}).then((canvas) => {
  saveAs(canvas.toDataURL("image/jpeg"), "capture.jpeg");
});
```

This works fine for most of the elements but not for the table.

This is what we get. The outside border width is 1px, but the inside borders are 2px.

![original table capture](https://cdn.hashnode.com/res/hashnode/image/upload/v1716727362548/7bb7845e-252f-44d0-8f38-862f88dffce5.png align="center")

You might say... "Make the outer border 2px to match the inside". Of course, that's a solution too, but this wasn't my personal project. I have a design for it and I do not have the power to change the design... 🫠

\* I found some of the stack overflow talks about `border-collapse: collapse;`. This only eliminate nested border look. So this wasn't my solution.

## Delete Overlapping Borders

One common solution I found on the Internet is reducing overlaps.

Most of the browsers automatically reduce overlapping borders. Therefore, when I see my code on a browser, there are no double borders. (Open the developer tool and check the cell styles. It will show that only the left and bottom borders are active even though I added borders for all sides)

But the capture won't reduce automatically. So... need to style it manually.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716892202899/1d206860-bc85-48c2-b788-ff6d05b1fd45.png align="center")

I added **a top border** for `thead`, and **a left border** and **a bottom border** for cells. And **a right border** for the last cell. (I think if the border does not overlap, anything is fine... but if I am wrong, please tell me 🙏)

So this is the final result, all borders are the same width 🙌

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716728281281/bcc396c1-d2a5-44a2-b8c3-533a13b7beb4.png align="center")

## Complex Table

It worked fine until I encountered **merged cells** and **striped rows.** When I use `html2canvas`, the text in merged cells disappears. Additionally, the borders of the merged cells are not displaying correctly... 😭 (I didn't remove overlapping borders for this example)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1717202141180/e5fca23e-e8cd-4e88-9faf-6989f493dbc6.png align="center")

### Use `dom-to-image`

I made the decision to search for a new library instead of modifying the styles (don't ask me why 🫣). While researching, I came across [`dom-to-image`](https://github.com/tsayen/dom-to-image). Although it hasn't updated since 2017, but.... I decided to give it a try.

```typescript
import { saveAs } from "file-saver";
import domtoimage from "dom-to-image";

let element = document.getElementById("capture") as HTMLElement;

domtoimage
  .toBlob(element, {
    width: element.clientWidth,
    height: element.clientHeight,
  })
  .then((blob: Blob) => saveAs(blob, "capture.jpeg"))
  .catch((error: Error) => {
    console.error("Fail to save", error);
  });
```

And you know what? It works perfectly. 🙌 No overlapped borders or disappearing text. 🥳

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1717204448411/a059f584-4d0a-401b-ad7d-90a639c25602.png align="center")

After a brief moment of excitement, the project manager is hesitant to use a library that hasn't been updated in a long time. I get it, but... but... 😭🫠🙈

### Use `dom-to-image-more`

The project manager suggested using [dom-to-image-more](https://github.com/1904labs/dom-to-image-more) which is a fork of the dom-to-image with some important fixes. As of writing this article, it seems that it is still being updated.

Just change the import and reuse other part.

```typescript
import { saveAs } from "file-saver";
import domtoimage from "dom-to-image-more";

let element = document.getElementById("capture") as HTMLElement;

domtoimage
  .toBlob(element)
  .then((blob: Blob) => saveAs(blob, "capture.jpeg"));
```

And result is...

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718108430290/89c1326d-1cad-47ae-8683-481b09e9018f.png align="center")

What...🫢 I did not expect this result.

The text inside the cell did not disappear, but the border and spacing were changed. I might be able to set print styles for the element. I asked my project manager if he wanted me to change the style and make it work, but he said no. Therefore, we decided to skip using this library.

### Use `html-to-image`

Luckily I found another library through [a medium post by *Code to Coin*](https://betterprogramming.pub/heres-why-i-m-replacing-html2canvas-with-html-to-image-in-our-react-app-d8da0b85eadf).

In the article, he was comparing the performance time of the 2 libraries.

> The average difference in performance was 86.3985 ms. This means that on average, `html-to-image` was almost 71 times faster than `html2canvas`!

I was having time issues as well, so if this works fine, I might replace all html2canvas later🤔.

```typescript
import { saveAs } from "file-saver";
import * as htmlToImage from "html-to-image";

let element = document.getElementById("capture") as HTMLElement;

htmlToImage
  .toBlob(element, {
    canvasWidth: element.clientWidth / 2,
    canvasHeight: element.clientHeight / 2,
  })
  .then((blob: Blob) => saveAs(blob, "capture.jpeg"));
```

I use `toBlob` and added `canvasWidth` and `canvasHeight` to match with other results. (There is a `toPng`, `toJpeg`, `toSvg` functions available)

And the result is this 👇

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718112331678/2eedaf18-c99b-45e5-bc00-83efd552be09.png align="center")

It looks fine. There is no difference from the `dom-to-image` result.

The last release was a year ago, but my manager is okay with it, so finally I could finish my task. 😭

## Wrap up

I ended up replace `html2canvas` with `html-to-image` so that I don't have to change existing table styles. However, if it's not a complex table, I think I'd reduce the overlapping borders.

If I had more time to experiment with styles, I might have found another way, or maybe I could fork the library and do something? If you know a better way or a different library, please let me know. 🤩

\* Find the code for this article on [GitHub](https://github.com/yoniakabecky/blog-sample-code/tree/main/app/demo/01-table-borders).

# **References**

%[https://betterprogramming.pub/heres-why-i-m-replacing-html2canvas-with-html-to-image-in-our-react-app-d8da0b85eadf] 

%[https://github.com/yoniakabecky/blog-sample-code/]
