Issue with CSS - Problem with Text Stroke (-webkit-text-stroke)

I've been working on a personal project using NextJs and TailwindCSS. Upon completion, I decided to check my progress using different browsers only to discover that the text stroke effect is not displaying properly in all browsers except Chrome.

Here's what I'm experiencing:

https://i.sstatic.net/7lXgc.jpg

Here's the desired outcome:

https://i.sstatic.net/JxV6H.jpg

Below is the code snippet used:

<div className="outline-title text-white pb-2 text-5xl font-bold text-center mb-12 mt-8">
      Values &amp; Process
</div>

CSS styling applied:

.outline-title {
  color: rgba(0, 0, 0, 0);
  -webkit-text-stroke: 2px black;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

If anyone can explain this issue or provide guidance on how to resolve it, I would greatly appreciate it.

Current browser compatibility is shown here: https://i.sstatic.net/kN0te.jpg

Answer №1

-webkit-text-stroke and Variable Fonts Compatibility Issues

Update 2024: Solution with paint-order

Credit goes to HyoukJoon Lee's solution on "CSS Font Border?". The use of the SVG property paint-order for HTML text elements is supported by major rendering engines, resolving issues with variable fonts.

...

Reasoning Behind Rendering Challenges in Variable Fonts

The complexity of glyph construction in variable fonts leads to challenges with outline rendering using webkit-text-stroke, particularly due to seamless weight and width interpolations.

...

Solution: Opt for Static Font Versions

In cases of compatibility issues, consider using non-variable versions of the font like 'InterStatic' available on GitHub.

...

Workaround: JavaScript-Based Replacement Using SVG

An alternative method involves converting HTML elements to SVG text for greater control over stroke rendering, especially useful when facing challenges with -webkit-text-stroke.

...

Note:

  • Minor layout shifts may occur due to word splitting.
  • Changes to width-related properties won't automatically update without recalculating viewBox values.

Features:

  • Selectable text with retained formatting from parent elements
  • Responsive text behavior during resizing and font adjustments

Answer №2

Some browsers do not support the -webkit-text-stroke property due to compatibility issues. One alternative is to use text shadows to achieve a similar outline effect.

I hope this solution works for you!

.outline-title {
font-family: sans-serif;
   color: white;
   text-shadow:
       1px 1px 0 #000,
     -1px -1px 0 #000,  
      1px -1px 0 #000,
      -1px 1px 0 #000;
      font-size: 50px;
}
<div class="outline-title text-white pb-2 text-5xl font-bold text-center mb-12 mt-8">
      Values &amp; Process
</div>

---- UPDATE ---

https://i.sstatic.net/2HQLN.png

Answer №3

One way to achieve this is by overlaying a duplicate of the text over the existing text. This method typically yields satisfactory outcomes:

By utilizing pseudo-elements, you can achieve the same result without adding an extra element to your HTML markup:

.broken {
  -webkit-text-stroke: 2px black;
}

.fixed {
  position: relative;
  /* The stroke width should be doubled to account for the covered area */
  -webkit-text-stroke: 4px black;
}
/* Display a second instance of the text on top of the original */
.fixed::after {
  content: attr(data-text);
  position: absolute;
  left: 0;
  -webkit-text-stroke: 0;
  pointer-events: none;
}


div { font-family: 'Inter var'; color: white; }
/* (optional) tweaks to align the shapes produced by both methods better */
.broken { font-weight: 800; font-size: 40px; }
.fixed { font-weight: 600; font-size: 39px; letter-spacing: 1.2px; }
<link href="https://rsms.me/inter/inter.css" rel="stylesheet">

Before:
<div class="broken">
  Values &amp; Process
</div>

After:
<div class="fixed" data-text="Values &amp; Process">
  Values &amp; Process
</div>

It's worth noting that using an additional element may be more beneficial for accessibility compared to employing a pseudo-element. With a separate element, you can apply aria-hidden to prevent screen readers from reading the text multiple times.

An example illustrating the concept:

.broken {
  -webkit-text-stroke: 2px black;
}

.fixed {
  position: relative;
  /* The stroke width should be doubled as half will be hidden under the original text */
  -webkit-text-stroke: 4px black;
}
/* Overlay the duplicated text atop the original one */
.fixed span {
  position: absolute;
  left: 0;
  -webkit-text-stroke: 0;
  pointer-events: none;
}


div { font-family: 'Inter var'; color: white; }
/* (optional) adjustments to make the two approaches produce more similar shapes */
.broken { font-weight: 800; font-size: 40px; }
.fixed { font-weight: 600; font-size: 39px; letter-spacing: 1.2px; }
<link href="https://rsms.me/inter/inter.css" rel="stylesheet">

Before:
<div class="broken">
  Values &amp; Process
</div>

After:
<div class="fixed">
  Values &amp; Process
  <span aria-hidden="true">Values &amp; Process</span>
</div>

Answer №4

Dealing with a similar issue involving the 'Nunito' font, I found a solution that worked for me:

  1. First step is to download a font editor -
  2. Once you have the font editor, open your font in it
  3. Select all by pressing Ctrl + A
  4. In the editor's menu, go to Element > Overlap > Union
  5. After making the necessary changes, save the new version of the font

You can see an example of how the font looks after these modifications here: https://i.sstatic.net/zgPbd.png

To learn more about why this bug occurs and how to fix it, check out this post: https://github.com/rsms/inter/issues/292#issuecomment-674993644

Answer №5

This problem arises when variable-width fonts are used in specific browsers. The reason behind this issue remains unclear to me

Explore more about this topic here.

Answer №6

My strategy for handling this situation is as follows:

  • Include 2 texts, with one overlapping the other using absolute positioning
  • Enclose both texts in a relative container

Here is an example code snippet (suitable for use with NextJs and TailwindCSS):

import { ComponentProps } from 'react'

export const TextWithStroke = ({ text, ...props }: ComponentProps<'div'> & { text: string }) => {
      return (
        <div
          {...props}
          style={{
            position: 'relative',
            ...props.style
          }}>
          <p className="text-stroke">{text}</p>
          <p className="top-0 absolute">{text}</p>
        </div>
      )
    }

The class text-stroke refers to the property -webkit-text-stroke, which I have defined in a global CSS file like this:

@layer utilities {
    .text-stroke {
        -webkit-text-stroke: 5px #4DDE4D;
    }
}

This setup produces the following result:
https://i.sstatic.net/2iAZ6.png

Answer №7

The issue lies in the default font (inter) that is included with next.js. Unfortunately, Google Inter font is not compatible with this. The solution is to simply switch to a different font family.

For example, you can use font-serif like so:

<div className="outline-title pb-2 text-9xl font-bold text-center mb-12 mt-8 font-serif">
      Values &amp; Process
    </div>

Answer №8

When I encountered similar difficulties while utilizing Montserrat, I found myself in need of displaying the background instead of the text color with a white stroke. The information provided by @herrstrietzel was quite beneficial. Initially, I was uncertain about how to render the text color transparent without revealing awkward joints in the font. My solution involved using the paint-order property.

paint-order: stroke fill;

Subsequently, I discovered that by specifying an RGBA color and adjusting the opacity to a level that accentuates the background while maintaining a sense of transparency in the text color, I was able to achieve my desired outcome.

https://i.sstatic.net/oJIoY8tA.png

In this case, I selected a color from the background and fine-tuned its opacity to ensure that the background is perceptible to some extent.

Utilizing the RGBA color prevented the peculiar curves that appear when employing the transparent color value.

https://i.sstatic.net/wjZZco9Y.png

Answer №9

There was a similar issue I encountered in the past, I had initially set 'Montserrat' as my main font but then mistakenly applied Another font to one of the elements. However, switching from 'Montserrat' to 'Poppins' resolved the problem :P

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

Issue: A problem occurred with the function (0, USe.isError) during the initialization of Prisma in a NEXT.js application with PostgreSQL

My attempt at creating an E-commerce site using Next.js, Prisma, and PostgreSQL hit a snag when I followed these steps: step 1: npx create-next-app@latest . step 2: npm i --save-dev ts-node step 3: npm install prisma --save-dev step 4: npx prisma init ...

Explore a variety of themes for the antd design token

Is there a way to access the text color of both the default and dark themes using design tokens? I am looking for a method to seamlessly switch between the two color schemes based on specific conditions, without having to change the entire theme. For ins ...

Oops! There seems to be a server error with the PDFDownloadLink API. It appears that you are trying to use this web-specific API on Node, or perhaps your bundler is not loading react-pdf properly

I have developed a Report card generator in Next.js, and I am currently experimenting with the use of @react-pdf/renderer to generate PDFs before integrating it into my main project. However, I am encountering an error that I can't seem to resolve. S ...

The title attribute in Vue3 is updated through props, but computed properties remain unaffected

I incorporated an external library into my project using Vue3. The component I am utilizing is sourced from a third-party library [Edit: Upon realizing that the GitHub repository for this library is no longer being maintained, I have updated the code to re ...

The Vercel Edge Runtime's Notion API is returning a 400 status code

When accessing API routes in Next.js through Vercel Edge Runtime, such as the Notion API endpoints for Retrieving a database or Querying a database, a 400 invalid_request_url response is returned: {"object":"error","status":40 ...

Error with Firebase. Make sure the URL for your Firebase Realtime Database instance is set up correctly

Currently, I am utilizing the getServerSideProps function to retrieve data from my Firebase database for my Next.js application. This is how my code snippet appears: export async function getServerSideProps(context) { const session = await getSession( ...

Tips on presenting our data using JSON structure

Hey there! I'm new to Next JS and I'm looking to showcase the data from my index.js file in JSON format in my dynamicid.js file. Can anyone guide me on how to achieve this? index.js In my index.js file, I currently display my output but now I ...

Using img-fluid in CSS to dynamically resize database-supplied images, providing a consistent and optimized viewing

Currently, I am working on a bootstrap site that operates as a CMS. This allows users to select a layout and drag images into DIV containers (bootstrap columns) for the purpose of saving and displaying them on digital displays. Although most functionaliti ...

Can an error be thrown from a catch block within a Promise in a NodeJs environment?

While working with NextJs, I encountered an issue in my API code. In one of my api pages (/api/sendData.ts), there is a method call process() that belongs to a separate class platform.ts. This is the structure of my API code (in sendData.ts): try { pla ...

Is there a way to align this button perfectly with the textboxes?

https://i.sstatic.net/ODkgE.png Is there a way to align the left side of the button with the textboxes in my form? I'm using bootstrap 3 for this. Here is the HTML code for my form. I can provide the CSS if needed. Thanks. h1 { font-size:83px; ...

Shifting and implementing various styles across numerous elements at the same time

There is an anchor tag containing two spans... <a class="banner-logo" href="/search"><span id="banner-logo-hello">Hello</span><span id="banner-logo-world">World</span></a> When hovering over the anchor tag, I want to c ...

Bug with the button and text input feature in Firefox

I am facing a strange issue where the button and input have the same CSS (except for the background), but Firefox is displaying them differently. This problem does not occur in IE or Chrome. #searchInput { width: 80%; margin: 0 auto; display: ...

What is the solution to eliminating the horizontal scroll bar on a responsive website?

Currently in the process of developing a responsive website, I have encountered an issue with excess empty space appearing on the right side when scrolling horizontally. Utilizing overflow-x: hidden successfully eliminates the horizontal scroll; however, t ...

Invoke a function using the output of a different function

There is a function whose name is stored in the value of another function, and I need to invoke this function using the other one. The function I need to call is popup() random() = 'popup()' if ($.cookie('optin-page')) { } I attemp ...

Can the React Context API in a NextJS application disrupt the Static Site Generator functionality?

My inquiries revolve around nextJS and SSG (static site generator). 1 - My intention is to handle the app state on a global level using react's context api. The information I have suggests that utilizing redux in a next js app disables SSG. Would imp ...

Issue with importing CSS file in Vaadin Java

Currently, I am tackling the eighth part of the Vaadin Tutorial series. Watch the video here: https://www.youtube.com/watch?v=ttuBu8dYNn0 For the text version, visit: I am currently facing a challenge with the final step of importing the provided CSS fi ...

What steps can be taken to address the build problem with Angular version 13?

Encountering a problem while working with Angular 13: https://i.sstatic.net/CbAUhh6r.png Attempting to build using ng build --configuration=test, however facing errors as mentioned above. Interestingly, if I remove the reference to bootstrap.min.css in t ...

The hover effect disappears when the mouse is on the edge

When my mouse is on the bottom border, the hover effect does not work. How can I make the bottom border part of the list container and count as one element? Currently, when the mouse is on the bottom border, the element loses its hover effect. <style&g ...

Switch the CSS class for the currently selected link

There are 5 links on the page. When I click on each link, it changes color. However, when I move my cursor to another area of the page, the active link loses focus and I can't show its current state. Can you please advise me on how to fix this issue? ...

"Mastering the art of CSS: when the cascade goes

Can someone assist me with a tricky cascading style problem that is not so straightforward? I need to override a CSS child style with another style of equal importance (012), without changing its order in the CSS sheet... To see a concrete example, pleas ...