Beyond Media Queries: Using Newer HTML & CSS Features for Re...

Beyond Media Queries: Using Newer HTML & CSS Features for Re…

Beyond using media queries and modern CSS layouts, like flexbox and grid, to create responsive websites, there are certain overlooked things we can do well to make responsive sites. In this article, we’ll dig into a number tools (revolving around HTML and CSS) we have at the ready, from responsive images to relatively new CSS functions that work naturally whether we use media queries or not.

In fact, media queries become more of a complement when used with these features rather than the full approach. Let’s see how that works.

Truly responsive images

Remember when we could just chuck width: 100% on images and call it a day? That still works, of course, and does make images squishy, but there are a number of downsides that come with it, the most notable of which include:

  • The image might squish to the extent that it loses its focal point.
  • Smaller devices still wind up downloading the full size image.

When using images on the web, we have to make sure they’re optimized in terms of their resolution and size. The reason is to ensure that we have the right image resolution to fit the right device, so we don’t end up downloading really large and heavy images for smaller screens which could end up reducing the performance of a site. 

In simple terms, we’re making sure that larger, high-resolution images are sent to larger screens, while smaller, low-resolution variations are sent to smaller screens, improving both performance and user experience.

HTML offers the <picture> element that allows us specify the exact image resource that will be rendered based on the media query we add. As described earlier, instead of having one image (usually a large, high-resolution version) sent to all screen sizes and scaling it to the viewport width, we specify a set of images to serve in specific situations.

  <source media="(max-width:1000px)" srcset="">
  <source media="(max-width:600px)" srcset="">
  <source media="(max-width:400px)" srcset="">
  <img src="" alt="picture"">

In this example, picture.png is the full-size image. From there, we define the next-largest version of the image,, and the size reduces in descending order until the smallest version, Note that we’re still using media queries in this approach, but it’s the <picture> element itself that is driving the responsive behavior rather than defining breakpoints in the CSS.

The media queries are added appropriately to scale with the sizes of the picture:

  • Viewports that are 1000px and above get picture.png.
  • Viewports that are between 601px and 999px get
  • Viewports that are between 401px and 600px get
  • Any thing smaller than 400px gets

Interestingly, we can also label each image by image density —  1x, 2x, 3x and so forth — after the URL. This works if we have made the different images in proportion to each other (which we did). This allows the browser to determine which version to download based on the screen’s pixel density in addition to the viewport size. But note how many images we wind up defining:

  <source media="(max-width:1000px)" srcset=" 1x, 2x, 3x">
  <source media="(max-width:600px)" srcset=" 1x, 2x, 3x">
  <source media="(max-width:400px)" srcset=" 1x, 2x, 3x">
  <img src="" alt="picture"">

Let’s look specifically at the two tags nested inside the <picture> element: <source> and <img>.

The browser will look for the first <source> element where the media query matches the current viewport width, and then it will display the proper image (specified in the srcset attribute). The <img> element is required as the last child of the <picture> element, as a fallback option if none of the initial source tags matches.

We can also use image density to handle responsive images with just the <img> element using the srcset attribute:

 srcset="  flower4x.png 4x,  flower3x.png 3x,  flower2x.png 2x,  flower1x.png 1x "

Another thing we can do is write media queries in the CSS based on the screen resolution (usually measured in dots per inch, or dpi) of the device itself and not just the device viewport. What this means is that instead of:

@media only screen and (max-width: 600px) {
  /* Style stuff */

We now have:

@media only screen and (min-resolution: 192dpi) {
  /* Style stuff */

This approach lets us dictate what image to render based the screen resolution of the device itself, which could be helpful when dealing with high resolution images. Basically, that means we can display high quality pictures for screens that support higher resolutions and smaller versions at lower resolutions. It’s worth noting that, although mobile devices have small screens, they’re usually high resolution. That means it’s probably not the best idea rely on resolution alone when determining which image to render. It could result in serving large, high-resolution images to really small screens, which may not be the version we really want to display at such a small screen size.

body {
  background-image : picture-md.png; /* the default image */

@media only screen and (min-resolution: 192dpi) {
  body {
    background-image :; /* higher resolution */

What <picture> gives us is basically the ability to art direct images. And, in keeping with this idea, we can leverage CSS features, like the object-fit property which, when used with object-position, allows us to crop images for better focal points while maintaining the image’s aspect ratio.

So, to change the focal point of an image:

@media only screen and (min-resolution: 192dpi) {
  body {
    background-image :;
    object-fit: cover;
    object-position: 100% 150%; /* moves focus toward the middle-right */

Setting minimum and maximum values in CSS

The min() function specifies the absolute smallest size that an element can shrink to. This function proves really useful in terms of helping text sizes to properly scale across different screen sizes, like never letting fluid type to drop below a legible font size:

html {
  font-size: min(1rem, 22px); /* Stays between 16px and 22px */

min() accepts two values, and they can be relative, percentage, or fixed units. In this example, we’re telling the browser to never let an element with class .box go below 45% width or 600px, whichever is smallest based on the viewport width:

.box {
  width : min(45%, 600px)

If 45% computes to a value smaller than 600px, the browser uses 45% as the width. Conversely, if  45% computes to a value greater than 600px, then 600px will be used for the element’s width.

The same sort of thing goes for the max() function. It also accepts two values, but rather than specifying the smallest size for an element, we’re defining the largest it can get.

.box {
  width : max(60%, 600px)

If 60% computes to a value smaller than 600px, the browser uses 60% as the width. On the flip side, if 60% computes to a value greater than 600px, then 600px will be used as the element’s width.

And, hey, we can even set a minimum and maximum range instead using the minmax() function:

.box {
  width : minmax( 600px, 50% ); /* at least 600px, but never more than 50% */

Clamping values

Many of us have been clamoring for clamp() for some time now, and we actually have broad support across all modern browsers (sorry, Internet Explorer). clamp() is the combination of the min() and max() functions, accepting three parameters:

  1. the minimum value,
  2. the preferred value, and
  3. the maximum value

For example:

.box {
  font-size : clamp(1rem, 40px, 4rem)

The browser will set the font at 1rem until the computed value of 1rem is larger than 40px. And when the computed value is above 40px? Yep, the browser will stop increasing the size after it hits 4rem. You can see how clamp() can be used to make elements fluid without reaching for media queries.

Working with responsive units

Have you ever built a page with a large heading or sub-heading and admired how great it looked on a desktop screen, only to check it on a mobile device and find out that’s it’s too large? I have definitely been in this situation and in this section I’ll be explaining how to handle such problems.

In CSS, you can determine sizes or lengths of elements using various units of measurements, and the most used units of measurements includes: px, em, rem, %, vw, and vh. Although, there are several more units that aren’t used as frequently. What’s of interest to us is that px can be considered an absolute unit, while the rest are considered relative units.

Absolute units

A pixel (px) is considered an absolute unit mainly because it’s fixed and does not change based on the measurement of any other element. It can be considered as the base, or root, unit that some other relative units use. Trying to use pixels for responsive behavior can bump into issues because it’s fixed, but they’re great if you have elements that should not be resized at all.

Relative units

Relative units, like %, em, and rem, are better suited to responsive design mainly because of their ability to scale across different screen sizes.

vw: Relative to the viewport’s width
vh: Relative to the viewport’s height
rem: Relative to the root (<html>) element (default font-size is usually 16px )
em: Relative to the parent element
%: Relative to the parent element

Again, the default font size for most browsers is 16px and and that’s what rem units use to generate their computed values. So, if a user adjusts the font size on the browser, everything on the page scales properly depending on the root size. For example, when dealing a root set at 16px, the number you specify will multiply that number times the default size. For example:

.8rem = 12.8px (.8 * 16)
1rem = 16px (1 * 16)
2rem = 32px (2 * 16)

What if either you or the user changes the default size? As we said already, these are relative units and the final size values will be based off of the new base size. This proves useful within media queries, where you just change the font size and the entire page scales up or down accordingly.

For example, if you changed the font-size to 10px within the CSS, then the calculated sizes would end up being:

html {
  font-size : 10px;
1rem = 10px (1 * 10)
2rem = 20px (2 * 10)
.5rem = 5px (.5 * 10)

Note: This also applies to percentage %. For instance:

100% = 16px;
200% = 32px; 
50% = 8px;

And what’s the difference between rem and em units? It’s what the unit uses as its base element. rem calculates values using the font size of the root (<html>) element, whereas an element declaring em values references the font size of the parent element that contains it. If the size of specified parent element is different from the root element (e.g. the parent elements is 18px but the root element is 16px) then em and rem will resolve to different computed values. This gives us more fine-grained control of how our elements respond in different responsive contexts.

vh is an acronym for viewport height, or the viewable screen’s height. 100vh represent 100% of the viewport’s height (depending on the device). In the same vein, vw stands for viewport width, meaning the viewable screen’s width of the device, and 100vw literally represents 100% of the viewport’s width.

Moving beyond media queries

See that? We just looked at a number of really powerful and relatively new HTML and CSS features that give us additional (and possible more effective) ways to build for responsiveness. It’s not that these new-fangled techniques replace what we’ve been doing all along. They are merely more tools in our developer tool belt that give us greater control to determine how elements behave in different contexts. Whether it’s working with font sizes, resolutions, widths, focal points, or any number of things, we have more fine-grain control of the user experience than ever before.

So, next time you find yourself working on a project where you wish you had more control over the exact look and feel of the design on specific devices, check out what native HTML and CSS can do to help — it’s incredible how far things have come along.

Source link


Stroke Text CSS: ? The Definitive Guide

In this tutorial I will show you how to create the stroke text CSS effect.

Before we go into the HTML and CSS code, if you only need to create a stroke text image, check out this tutorial and learn how to outline text in Photoshop.

Or, if you don’t have Photoshop, you can use the free online tool MockoFun which even has a dedicated stroke text tutorial.

Text With Border

So, how does one add stroke text or outline text in CSS & HTML?

There’s actually more than one way to do this, and as I would like this to be a definitive guide, I will go through all the methods with examples and source code. I will show you how to add a color outline to web text using CSS.

Let’s begin!

Add Stroke To Text Using CSS -webkit-text-stroke

CSS Stroke Text

As an example, let’s add a black stroke to a text. I will start with some HTML code:

<span class="stroke-text">STROKE TEXT</span>

And the CSS code:

  -webkit-text-stroke:5px black;

See the Pen CSS Stroke Text Using -webkit-text-stroke by Ion Emil Negoita (@inegoita) on CodePen.16997

Pretty straight forward, we make the text transparent – though this is not necessary, but I only want to the outline of the text to be visible and not the body of the letters. Then, the -webkit-text-stroke property adds a black outline stroke 5px thick. You can change this to get thicker outline text or a thinner outline, depending on what effect you want to obtain.

The good news:

You can use this to stroke text in CSS on all Webkit based browsers (like Chrome or Edge) and Firefox too.

The bad news:

This is a non-standard feature, so not something you can rely 100%.

It’s not supported on all browsers and according to this property does not yet appear in any W3C specification. Was briefly included in a spec as the text-outline property, but this was removed.

Just to give you a hint of what you can create with this text stroke CSS property, here’s my Cyber Space text effect part of the 80s fonts text effects gallery.

80s Font Stroke Text


Adding Stroke To Text Using text-shadow

Another method to outline text in CSS is by using shadows. CSS allows adding multiple shadows to a text element via the property text-shadow.

So, let’s make a white on white text and add 4 red shadows to it. Offset the 4 shadows by 1px up, left, down and right. Here’s the HTML code:

<span class="stroke-text">STROKE TEXT</span>

and the CSS code:

  text-shadow:1px 0 0 red,0 1px 0 red,-1px 0 0 red,0 -1px 0 red;

Here’s a graphical representation of what’s going on and how the CSS text stroke effect is achieved using text shadows:

CSS Text Stroke Using Shadow

Perfect, isn’t it?

Well, not exactly, but pretty damn good. Let’s point out some draw backs and solutions for it.

First, if we need to modify the text outline thickness or color we need to change it in multiple places, and this can be tedious.

CSS offers us quite an elegant solution which I use quite often for convenience and that is CSS variables. You can read more about CSS variable here, but what you need to know is that if you in your CSS you have to repeat values over and over again, CSS variables are a tremendous help.

Using CSS Variables To Configure The Text Stroke Color And Thickness

Basically you define a CSS variable like this: --my-variable:value. Then, throughout your CSS code if you need that value simply use property:var(--my-variable);

So, change the CSS code above like this:

  text-shadow: var(--stroke-width)  0 0 var(--stroke-color),
    calc(var(--stroke-width) * -1) 0 0 var(--stroke-color),
    0 var(--stroke-width) 0 var(--stroke-color),
    0 calc(var(--stroke-width) * -1) 0 var(--stroke-color);

The --stroke-color variable stores the color for the text stroke and --stroke-width stores the width of the stroke. Then in the text shadow we use those variables. This allows making changes only in one place if we were to modify the color or the width of the text stroke.

Pretty neat, isn’t it?

In the text-shadow property, I’ve made use of the CSS calc function to allow me to multiply the text stroke width by -1 for the up and left shadow directions.

If you start playing around with this and change the thickness of the text stroke you will notice that for larger values, something is wrong at the corner of the letters.

And so we come to our second draw back:

CSS Stroke Text

We see some breaks in the text stroke because we are only using 4 shadows that we shift on 4 directions.

So, what should we do to fix this?

The answer is simple: add more shadows!

Hang on to your hats kids and take out your math notebooks. This is a “Definitive Guide to Stroke Text” after all, so we need to be thorough.

If we add more shadows to our text, we need to figure out how to shift those shadows around our text to cover all the gaps in the text outline. Intuition says that we should spread them evenly on a circle with a radius equal to the width of the text stroke.

And, intuition is right!

To calculate the offsets of the shadows we use the polar coordinates formulas:

x = r * cos(alpha)
y = r * sin(alpha)

Where x and y are the offset values, r is the radius of the circle (actual amount that we want to offset by which translates into the thickness of the text stroke) and alpha is the angle by which we want to divide the circle into.

We can assign values to alpha depending on how many shadows we want to add to create our text stroke.

For example, for 8 shadows we divide 2*PI (the full circle) by 8 and we get an angle of PI/4. Then if we assign values to alpha with a step of PI/4 like 0, PI/4, PI/2, … until we complete the circle, we should get our 8 shadows offsets perfectly aligned on a circle.

CSS Stroke Text

The more shadows we add, the smoother the CSS text stroke becomes for larger values of the stroke width. There are no trigonometric function in CSS yet, so we need to calculate the values ourselves.

Let’s modify the HTML and CSS code to add a smooth text stroke with 16 shadows:

<span class="stroke-text smooth-16">STROKE TEXT</span>

and add the CSS for the smooth text stroke:

.smooth-16 {
  text-shadow: calc(var(--stroke-width) * 1) calc(var(--stroke-width) * 0) 0
    calc(var(--stroke-width) * 0.9239) calc(var(--stroke-width) * 0.3827) 0
    calc(var(--stroke-width) * 0.7071) calc(var(--stroke-width) * 0.7071) 0
    calc(var(--stroke-width) * 0.3827) calc(var(--stroke-width) * 0.9239) 0
    calc(var(--stroke-width) * 0) calc(var(--stroke-width) * 1) 0
    calc(var(--stroke-width) * -0.3827) calc(var(--stroke-width) * 0.9239) 0
    calc(var(--stroke-width) * -0.7071) calc(var(--stroke-width) * 0.7071) 0
    calc(var(--stroke-width) * -0.9239) calc(var(--stroke-width) * 0.3827) 0
    calc(var(--stroke-width) * -1) calc(var(--stroke-width) * 0) 0
    calc(var(--stroke-width) * -0.9239) calc(var(--stroke-width) * -0.3827) 0
    calc(var(--stroke-width) * -0.7071) calc(var(--stroke-width) * -0.7071) 0
    calc(var(--stroke-width) * -0.3827) calc(var(--stroke-width) * -0.9239) 0
    calc(var(--stroke-width) * 0) calc(var(--stroke-width) * -1) 0
    calc(var(--stroke-width) * 0.3827) calc(var(--stroke-width) * -0.9239) 0
    calc(var(--stroke-width) * 0.7071) calc(var(--stroke-width) * -0.7071) 0
    calc(var(--stroke-width) * 0.9239) calc(var(--stroke-width) * -0.3827) 0

For convenience, I’ve created a JS function that generates the stroke text CSS code depending on how many shadows you want to have. Here’s the code:

text-shadow from smooth-16 was created with steps = 16
function calculateStrokeTextCSS(steps) {
  var css = "";
  for (var i = 0; i < steps; i++) {
    var angle = (i * 2 * Math.PI) / steps;
    var cos = Math.round(10000 * Math.cos(angle)) / 10000;
    var sin = Math.round(10000 * Math.sin(angle)) / 10000;
    css +=
      "calc(var(--stroke-width) * " +
      cos +
      ") calc(var(--stroke-width) * " +
      sin +
      ") 0 var(--stroke-color),";

  return css;

Run this function with steps=16 and you will get the CSS value for the text-shadow property. Please note that this JS code does not have to be part of the page where you display the CSS stroke text. Here’s the Codepen snippet with where you can play with the code:

See the Pen CSS Stroke Text Using text-shadow by Ion Emil Negoita (@inegoita) on CodePen.16997

Now we have two perfectly valid methods for creating CSS stroke text, but since this is a definitive guide I will not stop here and I will show you a couple of extra alternatives for creating a text outline with CSS shadows.

QUICK TIP: This exact same method works for creating outline images from PNG images for example.

Add Stroke To Text Using CSS SVG Filters

If you don’t know about SVG filters or what you can do with them I strongly suggest you read this article about 80s fonts and SVG filter text retro effects. WARNING: prepare to be amazed ?

Basically, you can define SVG filters that you can then use in CSS with the filter property. In one of my recent articles I’ve made heavy use of CSS filters to create CSS image effects. But, in our case we will use SVG / CSS filters to add stroke to a text.

Here’s the HTML code along with the SVG filter definition:

<span class="stroke-text">STROKE TEXT</span>

<svg version="1.1" xmlns="//" xmlns:xlink="//" style="display:none;">
    <filter id="stroke-text-svg-filter">
      <feMorphology operator="dilate" radius="2"></feMorphology>
      <feComposite operator="xor" in="SourceGraphic"/>

and the CSS code:


which renders a blue outlined text like this:

CSS Outline Text

So, how does this work?

Well, the stroke-text-svg-filter SVG filter we apply to our text has two steps:

  • feMorphology with dilate takes the original text and “dilates” or enlarges the text in all directions by a radius of 2 pixels
  • feComposite with the operator="xor" performs a XOR operation which actually subtracts from the enlarged text the original text, such that we are left with a hollow text or outlined text

Change the thickness of the text stroke you have to modify the radius attribute in the SVG filter. To change the color of the text stroke, simply change the color CSS property in the stroke-text class.

This SVG filter also works for PNG images.

The only downside for this method of adding stroke to text is that the end result looks a bit coarse for bigger values of the radius. This is because the dilation algorithm tries to expand the letters in all directions which means that it might not render a true outline which should be equally sized in all directions.

Here’s the Codepen for adding stroke to text with SVG filters:

See the Pen CSS Stroke Text Using SVG Filters by Ion Emil Negoita (@inegoita) on CodePen.16997

SVG Text Outline

Besides SVG filters, we can create the text outline using SVG text and CSS specific for SVG.

Though not exactly an HTML and CSS only solution, this solution probably creates the best looking text outline effect.

SVG Stroke Text CSS

To create a text outline with SVG and CSS here’s the SVG code that you add in your HTML page:

<svg version="1.1" xmlns="//" xmlns:xlink="//" width="100%">
  <text class="stroke-text" x="50%" y="50%">SVG STROKE TEXT</text>

and the CSS code:


To quickly go over the code, the text SVG STROKE TEXT is added as an SVG text right in the middle of the SVG object (therefore the 50% set for the x and y).

The CSS code that actually controls the color and width of the text stroke or the text outline are the 2 CSS properties stroke and stroke-width. Please note that these properties will only work on SVG elements and NOT on HTML elements.

See the Pen SVG Text Outline by Ion Emil Negoita (@inegoita) on CodePen.16997

To create the multiple text stroke effect, just add a couple of extra <text> elements, offset them a bit and change the stroke color.

Create Double Outline Font Effect Or Multiple Outline Font Effect With SVG Stroke

While you’re on it, you should know that can also create some really cool double or multiple outline font effect with just a couple of modifications to the code above.

Double Outline Font

Simply add multiple text elements in the SVG with different stroke values in the CSS. Be careful to start with the thickest stroke and go on with thinner and thinner stroke values because the text elements will be placed on top of each other to form the multiple outline font effect.

Here’s the HTML code for the double font effect and the multiple font effect:

<svg version="1.1" xmlns="//" xmlns:xlink="//" width="100%" height="200">
  <text class="stroke-text thick color1" x="50%" y="50%">DOUBLE OUTLINE FONT</text>
  <text class="stroke-text" x="50%" y="50%">DOUBLE OUTLINE FONT</text>

<svg version="1.1" xmlns="//" xmlns:xlink="//" width="100%" height="200">
  <text class="stroke-text thicker color1" x="50%" y="50%">MULTIPLE OUTLINE FONT</text>
  <text class="stroke-text thick color2" x="50%" y="50%">MULTIPLE OUTLINE FONT</text>
  <text class="stroke-text color3" x="50%" y="50%">MULTIPLE OUTLINE FONT</text>

As you see I’ve added each effect in it’s own <svg> element. And the CSS code goes like this:







See the Pen Double Outline Font & Multiple Outline FontWith SVG Stroke by Ion Emil Negoita (@inegoita) on CodePen.16997

If you’ve reached this far, congrats! You’re now a CSS stroke text Jedi!

Want to be a Jedi master and know everything about CSS stroke text? Continue reading.

HTML5 Canvas Text Outline

I know I’ve said this before, but this article is meant to be a definitive guide to stroke text. That is why I decided to include ALL methods for creating stroke text or text outline in HTML, even without CSS.

Yes, it is possible to create outlined text using the HMTL5 canvas.

Let me show you how to do it!

HTML5 Canvas Text Outline

First, let’s setup the canvas with the following HTML code:

<canvas id="myCanvas" width="850" height="300"></canvas>

Then, using JavaScript let’s draw the outlined text like this:

var myCanvas = document.querySelector("#myCanvas");
var ctx = myCanvas.getContext("2d");

ctx.strokeStyle = "red";
ctx.lineWidth = 3;
ctx.font = "70px sans-serif";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.strokeText("CANVAS TEXT OUTLINE", myCanvas.width / 2, myCanvas.height / 2);

The important parts here are the strokeStyle and lineWidth settings that set the color and the thickness of the text outline. The strokeText() function does the actual drawing of the outlined text.

Here is the Codepen worksheet:

See the Pen HTML5 Canvas Text Outline by Ion Emil Negoita (@inegoita) on CodePen.16997

In Conclusion

I hope you found this article useful and worthy of being a true definitive guide to stroke text in CSS and not only. You now know more than one way to create stroke text or outline text in HTML, CSS and even HTML5 canvas.

If you know of alternative methods for creating stroke text in HTML and CSS please drop me a message and I’ll be happy to include it in this awesome and definitive guide!

Source link