Distorted text created by fillText on canvas in Chrome

When attempting to write text on canvas, I noticed that the text appears jagged, especially in Chrome 31.0.1650. I have experimented with

-webkit-font-smoothing:antialiased,text-shadow
but without success.

Does anyone have a solution to this issue? Thank you in advance.

Below is the style code used:

<style>
    #my_canvas{           
        -webkit-font-smoothing: antialiased;
        text-shadow: 1px 1px 1px rgba(0,0,0,0.004);
        text-indent: -9999px; 
    }                   
</style>

The code within the body tags:

<canvas id="my_canvas" height="300" width="2200"></canvas>
<script>
    var canvas = document.getElementById("my_canvas");
    var context = canvas.getContext("2d");
    context.imageSmoothingEnabled =true;
    context.fillStyle = "BLACK";
    context.font = "bold 100px Arial";
    context.fillText("A quick brown fox jumps over the lazy dOg", 50, 200);
</script>

Answer №1

This issue pertains to the text engine in Chrome.

Fortunately, there is a workaround solution available:

  • Create an off-screen canvas that is double the size of the on-screen canvas
  • Render the text onto the off-screen canvas using the appropriate scaling for font size and position
  • Display the off-screen canvas on the main canvas at a scaled-down size (half in this instance)

View live demo here

The difference may be subtle, but it ultimately enhances the quality. Here's an enlarged view:

Keep in mind, CSS does not impact the content within the canvas, only its elements. Image smoothing is automatically enabled and specifically affects images, not text or shapes (although we will utilize this feature for this technique).

var scale = 2;  // scale everything by x2.

var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');

ocanvas.width = canvas.width * scale;   // define new canvas size
ocanvas.height = canvas.height * scale;

// render the text on the off-screen canvas at double sizes
octx.fillStyle = "BLACK";
octx.font = "bold " + (100 * scale) + "px Arial";
octx.fillText("A quick brown fox jumps over the lazy dOg", 50*scale, 200*scale);

// crucial step: draw the off-screen canvas on the main canvas
context.drawImage(ocanvas, 0, 0, canvas.width, canvas.height);

By introducing interpolation into the process, Chrome initially renders the text roughly, then rasterizes it for further manipulation as an image.

When displaying the canvas (i.e., image) on our primary canvas at half the size, interpolation (sub-sampling) activates to apply a low-pass filter on pixels, resulting in a smoother appearance.

While this method may require more memory usage, the improved outcome justifies the minor sacrifice.

You may observe better results with a scale value of 2 rather than other figures due to the canvas' use of bi-linear interpolation instead of bi-cubic.

Why not implement transform like scale()? Chrome’s text rendering process transforms the vectors before rasterizing the text, achieving the same effect as scaling down after rendering at twice the size.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Could Chrome be miscalculating em unit values in media queries?

I have defined my media query breakpoints as shown below: @media screen and (max-width:48em){ /* phone */ } @media screen and (min-width:48.063em){ /* tablet */ } After using a PX to EM calculator to get the 48.063em value (as I was advised to us ...

Utilize CSS to break apart text (text = white space = text) and align text in a floating manner, allowing

Is there a way to use CSS to create a white space in the middle of text? Currently, I am manually breaking the text, which is not ideal. I am aware that there is a function that allows the text to end and start in another div, but unfortunately, it is not ...

Mobile device causing elements to resize unevenly

On my simple webpage, I have a combination of text and a table. Check out the HTML below: <body> <div id='stat'> <p class='subheading'>Stat of the Week: Average Final Standings</p> <p class='text&apo ...

How is it that the browser can determine my preferred font when all of them are labeled as Roboto?

Forgive my lack of expertise, but I have a question to ask... I've come across many examples that use the following method to load fonts from a local server: @font-face { font-family: "Roboto"; src: local(Roboto Thin), url("#{$robot ...

Achieving overflow behavior in a div with maximum height that contains another div with maximum height (Overflow issue persists)

Currently, I am utilizing Materializecss to showcase a modal window. Within this modal, there is a div Content that showcases items using ng-repeat. However, the issue arises when the content fills up and the css rule for my content-div fails to take effec ...

How can you create a jQuery fade in effect for a single <li> element

I'm in the process of developing a task management app that generates a new li element every time a user adds an item. However, I am facing an issue where fadeIn() is activating for every li on the page whenever a new item is added. Does anyone have s ...

Unique custom CSS and meta tag options for enhancing iPad/iPhone user experience

Currently, I am developing a web application that integrates Extjs components, PHP, and MySQL. My main goal is to ensure that my application looks correct on the iPad. Are there any specific CSS rules or meta tags that I should be implementing for optima ...

Creating a Circular Design with Text at the Center Using CSS

I'm facing a challenge with this https://i.sstatic.net/zQiF8.png The alignment of the icon is off. I would like to adjust it slightly upwards for better presentation. Below is my HTML (angular): // Icon component <div> <i><ng-c ...

Tips for displaying HTML elements beyond the boundaries of an iframe

Similar Inquiry: How can content from an IFRAME overflow onto the parent frame? I am in search of a potential solution for the following issue: There is a specific element with the style "position: absolute" within a page loaded into an iframe. Based ...

Help needed with CSS menu dropdown problem

Hello everyone, I am currently working on creating a menu for the top navigation of my website. My goal is to have a list of items appear below the menu when hovering over it with the mouse. Right now, I am testing this on a local HTML file before impleme ...

Bone Structure Styles - adaptable form

I'm currently working on a form using skeleton css and initially set it up with a three-column layout. However, I found that this created too much white space due to varying content lengths in each column. I would like to switch to a horizontal layout ...

What is the best way to center a button element horizontally within a div element?

I am looking for a way to center a button horizontally without adding CSS directly to the div element (for example, using <div style="text-align: center;">). My goal is to apply CSS code specifically to the button element. <div> <butto ...

Ensure the menu bar remains at the top of the page without using the position:

Check out this awesome fiddle here! My menu bar looks great at the top, but for some reason it won't stay in place when the user scrolls down. I've tried adding position:fixed to the CSS under the first #cssmenu, but it messes everything up. Her ...

What is the best way to create a sign-up box that appears on the same page when you click on the sign-up button

I am interested in implementing a 'sign up' box overlay at the center of my index page for new users who do not have an account. I would like them to be able to easily sign up by clicking on the 'sign up' button. Once they complete the ...

Guide on navigating to a specific page with ngx-bootstrap pagination

Is there a way to navigate to a specific page using ngx-bootstrap pagination by entering the page number into an input field? Check out this code snippet: ***Template:*** <div class="row"> <div class="col-xs-12 col-12"> ...

Ways to horizontally align 2 rows in React

I am in the process of developing a react app and I have encountered an issue with aligning the field names horizontally with their corresponding field values in multiple columns. Despite my efforts, the alignment still appears to be a bit off. Below is th ...

utilize the "li" element to function as a clickable button

My HTML code contains ul elements, as shown below: <ul class="nav" id="loadCategories"> <li class="sub-menu"><a href="#">Search by category</a> <ul class=""> <li><a href="#">Food</a></li> ...

The functionality of the custom file upload button is experiencing issues on Microsoft Edge

I've been working on creating a unique custom image upload button that functions perfectly in Chrome, Firefox, and Opera based on my testing. However, I'm facing an issue where it doesn't work properly in Microsoft Edge. Feel free to check ...

Using Bootstrap 4 to split lengthy text into multiple columns, similar to how it is done in Microsoft Word

Is there a way in Bootstrap4 to create MS Word-like multicolumn text flow? For example, in Word we have: https://i.sstatic.net/buCXu.png In Bootstrap4, the code below will generate a two-column grid: Example: <div class="row"> <div ...

Set a unique class for several elements depending on a given condition

Is there a way to assign a color class based on the element's value without looping through all elements? Check out my jsfiddle HTML <div> <ul> <li class="MyScore">90</li> <li class="MyScore"> ...