RSSAmplifier

Blog

Pqina

Pqina designs and builds performant, responsive, and highly polished web components.

pqina.nlRSS feed ↗65 posts

Latest posts

Animating The Dialog Element Using View Transitions

In this article we look at animating the <dialog> element using the View Transition API . We’ll follow progressive enhancement so it’s only used when supported and when the user allows animations to run. Let’s take a look at the non-view-transition demo below. This demo uses the Invoker Commands API and doesn’t require any JavaScript. Click the button to open the dialog. Hello World Hello World…

Updating CSS Border Radius When A Container Is Overflowing

In this article we’ll create a container element that dynamically adjusts its border-radius when its contents overflows. This week I learned about corner-shape via nerdy.dev . This led me down the path of adding big squircle corners to code blocks in the FilePond documentation. Great! But unfortunately they looked terrible when the scrollbar was active. I wondered if I could detect (with CSS only)…

How To Disable Right Click With JavaScript

In certain situations it might be useful to disable the browser right click context menu functionality. In this article I’ll quickly show you how it’s done. As the context menu is an important user interaction pattern we of course shouldn’t disable it lightly, let’s take a look. In my case I wanted to disable the right click interaction because it creates very strange situations when users drag an…

Crop An Image With Canvas

Cropping images in the browser can be done with the HTML5 canvas element . In this tutorial we’ll load an image from a local URL, crop the image, and present the result on the same page. Okay, first we need an image. Let’s use the image below, it’s located at the URL: https://pqina.nl/media/test.jpeg Our next goal is to load this image into a canvas element. Loading an image in a canvas element To…

Using CSS Color-Mix() to lower anchor underline opacity

A tiny code sample showing how to use the CSS color-mix function with currentColor to automatically lower the opacity of anchor underlines. We can use CSS color-mix to mix two colors and get a new color. The currentColor property holds the selected elements color value. Let’s combine them. a { text-decoration-color : color-mix ( in srgb , currentColor 30% , transparent ) ; } In this link to the…

Building A Birthdate Input Custom Element

In this article we look at a <birthdate-input> custom element that automatically orders input fields based on the browser locale. Useful for asking your customers to input their birthdate without presenting them with a datepicker. Why not a datepicker? Because humans remember their birthdate as a string of numbers and the day of the week is not relevant. Entering those numbers is easier than…

Animating And Transitioning CSS Custom Properties

This code animates a CSS property, and transitions a custom CSS property. The transition property is used in the animation. This combination works on Chrome, but unfortunately fails on Firefox and Safari. See animation below, followed by the code snippet. The Bar element should pulse, but at the start of the animation pulses should start at low opacity (similar to Foo) and slowly fade in, which is…

Creating CSS Spring Animations With The Linear Easing Function

While developing FilePond I wanted to run a CSS powered spring animation, but the CSS API didn’t support it natively. So I built this tiny tool to generate linear easing functions that simulate spring animations in CSS. The app below uses a Svelte spring to animate a transition from 0 to 1 , it then records the spring steps and converts them to a linear() CSS transition. As a bonus it also creates…

Using Web Bluetooth To Read BBQ Temperature Sensor Data

In this short read we’ll explore the Web Bluetooth API . We’ll connect with my Bluetooth BBQ thermometer. Then we’ll try to read out its data and listen to its temperature updates . At the end of the article you’ll have a good idea about what you can do with the Web Bluetooth API. A couple months ago we purchased the Hermanos Grill 5.0 Bluetooth BBQ thermometer . It supports up to 6 temperature…

What&#39;s the JavaScript version of sleep

There’s no sleep function in JavaScript, how can we make one? Let’s jump right in and write the function. function sleep ( milliseconds ) { return new Promise ( ( resolve ) => setTimeout ( resolve , milliseconds ) ) ; } It’s a basic function that when called returns a Promise that’s resolved after the given number of milliseconds. How do we use this function? // sleep for 1 second sleep ( 1000 ) .…

Flexible CSS Colors With Custom Properties

Let’s use CSS Custom Properties and calc() to create various CSS color effects, fasten your seatbelt, we’re going from 0 to 100 in 1.5 seconds. No time to waste, let’s go! Setting Up A Basic Color Scheme First we create a basic black text on white background style for our page. Note that in the :root selector we don’t use functional notations for our colors , we only set the numbers. < html > < p…

Create Crisp Image Borders With CSS Pseudo Elements

Transparent image borders can have contrast issues and look dull, let’s make them nice and crisp with this tiny CSS trick. The demo below shows a default half transparent image border. Boring border We can see that we lose contrast depending on the colors of the image near the border. The border looks nice when it’s near a contrasting area, but it kind of dissapears when near colors of the same…

Edit Images With Vue And Pintura

In this quick tutorial we’ll build a Vue image editor using Pintura a powerful JavaScript image and video editor SDK. We could build a complete image editor ourselves but that would literally take months, it would turn this quick tutorial into a not-so-quick tutorial. To get started we’ll set up a basic Vue Composition API based template and then add Pintura. < script setup > // Coming up next...…

Compress An Image Before Upload With JavaScript

In this quick tutorial we’ll use JavaScript to compress images selected with a file input element. We’ll compress images and save them back to the file input ready for upload. To make sure users can upload their images and prevent super big images from being uploaded we can compress image data before upload without bothering the user with all kinds of requirements. If you’re in a hurry, or find it…

Creating A Custom Svelte Media Query Store

In this short read we create a custom Svelte store to listen for Media Query changes. Super useful for when we want to react to the user changing the system theme or resizing the browser window. If you just want to get your hands on the ready made custom store you can jump to the code , else let’s explore how to create this custom store together. Svelte Custom Stores Svelte exports a set of…

Set Fill Color of SVG Background-image

A quick guide explaining how to change the color of an SVG when it’s used as a CSS background-image. If you want you can jump to the code , else we can explore how this works together. SVG Background Color Fill Demo We’ll start with a live demo, focus, hover, or click on the circle below and the background color will animate. I'm a cool circle button I’ll let the cat out of the bag. This is just a…

Edit Video and Images With React

In this short step by step tutorial we’ll set up Pintura Image Editor with its Video Editor extension to edit images and videos in the browser with React. We’re going to use Pintura because building a complete video editor from scratch is going to take ages. It let’s us skip over all the drama of dealing with various browser quirks and device differences to the fun part of integrating an image…

Upload An Image With Node.js

This short and concise guide shows how to set up image uploading with Node.js and Express. If you’re in a hurry you can jump to the complete code snippet else let’s set it up step by step together. Set Up The Server We’ll start with a basic Express server. Create a new folder and run npm init to generate a package.json file, then install Express. npm install express We’ll create an index.js file…

How To Clone A File With JavaScript

A short code example showing how to create a clone (or copy) from a File object received from a file input element. We’ll use a file input element as a source for the file. < input type = " file " /> < script > document . querySelector ( 'input' ) . addEventListener ( 'change' , ( e ) => { // we'll get the first file in the file input const original = e . target . files [ 0 ] ; // no file…

How To Set The Value Of A File Input

It’s always been impossible to set the value of a file input element with JavaScript , but this has changed last year and it’s now broadly supported, let’s see how it’s done. If you’re interested in why this is useful, read on below, else jump to the solution Why Is Setting The Value Of A File Input Useful? Being able to set the value of a file input comes in handy when we’ve edited an image in…

Annotate Images With JavaScript

In this tutorial we use Pintura, a JavaScript image editor, to quickly create a JavaScript image annotation solution to annotate and decorate user submitted images and photos. Our goal is to allows users to capture a photo using their mobile phone camera and then add annotations to it. We’ll start by setting up a basic HTML form, we’re not going to reinvent the wheel so let’s use Pintura a…

Overlap Elements With CSS Grid Instead Of Position Absolute

We can use CSS absolute positioning to overlap elements, but there’s some advantages to using CSS grid instead. Let’s explore using CSS grid as an alternative to position absolute. Overlapping Elements With Position Absolute Using the styles below we can position multiple child elements relative to the first parent element that has a position property, in this case the direct parent. < div class =…

Slim Image Cropper Alternative

In this short tutorial we’ll use the PinturaInput Web Component to replace a Slim Image Cropper instance with the more powerful Pintura Image Editor SDK . The <pintura-input> web component core functionality is similar to Slim, it handles image editing and uploading for one image. Because the component is using Pintura image editor it offers a lot more additional functionality than the image…

How To Upload An Image With PHP

In this quick tutorial we set up a basic HTML form to upload images with PHP , we also explore how to secure our PHP script so it can’t be abused by malicious users. Setting Up An Image Upload Form We start with a basic form. The form contains a submit button and has an action attribute. The action attribute points to the page the form will post all its contents to when the submit button is…

Fix HTML Video Autoplay Not Working

To optimise pages on this blog I recently replaced the animated GIFs with auto-playing videos. It required a couple tries to get it right, so here’s how it works. The video below won’t autoplay. < video autoplay > < source src = " video.mp4 " type = " video/mp4 " /> </ video > To fix this we add the muted attribute, this will disable the audio, making the video less intrusive. < video autoplay…

Convert An Image To A DataURL or Base64 String Using JavaScript

In this short tutorial we explore 3 different JavaScript methods to convert an image into a Base64 string. We look at converting a File object or Blob, a canvas element, and an image tag. In all examples below we assume we already have a <canvas> , <img> , File , or Blob object available. We’ll be converting images to DataURLs, we can use the function below to convert a DataURL to a Base64 string.…

Fix Google Search Console Mobile Usability Issues With A CSS Snippet

Every other week Google Search Console will send me an email reporting Mobile Usability issues on this blog. I’ll log in, click “Validate Fix”, and find that everything is just peachy. What’s going on? More importantly, how do we fix this? Usually Google Search Console reports one or all of the following issues: Clickable elements too close together Text too small to read Content wider than screen…

Generate Social Image Covers With Eleventy And Node-Canvas

This static blog is generated with Eleventy and all its social images are automatically generated with node-canvas . In this tutorial we’ll set up a basic version of this script so you can use it on your blog as well. For this tutorial we assume you already have an Eleventy site that you want to add social images to. If you need to set up a new site you can follow the Eleventy getting started…

Crop Images Before Upload With JavaScript

In this 3 minute tutorial we use CropGuide, a JavaScript image cropper, to crop images before they’re uploaded to our server without making any changes to existing file upload code. For this tutorial we’ll assume that a form with a file upload field has already been set up. Our goal is to add image editing to this field without having to modify any existing code. Why help your users Crop Images?…

Total Canvas Memory Use Exceeds The Maximum Limit

You’re using the HTML Canvas Element in your new web app and decide to quickly test on iOS Safari. Suddenly your canvas isn’t drawn and the console shows a yellow warning “Total canvas memory use exceeds the maximum limit”. What gives? While you were busy building, Safari was busy stuffing itself. Safari has a thing for hoarding <canvas> elements. When you’re done with a canvas, Safari will hold…

Canvas Area Exceeds The Maximum Limit

If there’s one thing I’m sure of it’s that Safari and the HTML canvas element aren’t sitting in a tree together. It’s 2022 and Safari still can’t handle canvas elements having more than 16777216 pixels. Safari simply cannot draw large canvas elements. The limit is set at 16.777.216 pixels. Create a canvas with more pixels and iOS Safari will tell us it exceeds the memory limit. When we open this…

Drawing Wrapped Text With The HTML Canvas Element

The HTML canvas element can draw text but it cannot wrap text. Text wrapping is complicated so in this tutorial, instead of breaking text lines with JavaScript, we’ll lean on native browser tech to draw wrapped text lines. Let’s try to draw the paragraph below to a canvas element. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Using Canvas fillText We’ll first give…

How To Prevent Scrolling The Page On iOS Safari 15

If we show a modal on iOS we need to prevent events inside the modal from interacting with the page behind the modal. On a previous episode of “Fun with Safari” we could use preventDefault() on the "touchmove" event but on iOS 15 that no longer works. Here we go. To make this work we need iOS to think that there is nothing to scroll. But how do we do this? We set the height of both the html and…

Use The JavaScript EyeDropper API To Select Colors On The Web

The EyeDropper API just landed in Chrome Canary. In this is a mini tutorial we’ll quickly look at how to use it in our web apps to select colors. Let’s get to it, the API is fairly straightforward. We create a new EyeDropper instance and can then ask it to open the eye dropper with the open method. The open method returns a Promise that resolves when a color is selected, it rejects if the user…

Styling Password Fields To Get Better Dots

Make the dots in a password field bigger with this basic CSS style. It’ll make it easier to see the number of dots in the field, helping both yourself and the visually impaired. Depending the font used the dots in the password field look like this. The font-family on the field below is set to sans-serif We can use the Verdana font to scale the dots to a more comfortable size.…

Create A Fade Out Overflow Effect Using CSS Mask-Image

Learn how to create an overflow fade out effect using CSS mask-image . This helps indicate to the user that there’s more content to be seen. Masking is very useful when overflowing content that’s placed over an image or a non-uniform background. Let’s take a look at the example below. When scrolling the custom scrollbar we can see that the content area overlows and the content is faded out. Lorem…

What Do HTML Elements Sound Like?

A video overview of HTML elements and how they sound when being navigated with assistive technology like the screenreader VoiceOver. What does a fieldset sound like? What does an img sound like? What does a list sound like? What does a br sound like? What does a time sound like? What does a fieldset sound like? A <fieldset> can be used to group similar fields together. Think radiobuttons,…

Integrating Uppy With Pintura Image Editor A JavaScript Image Editor

In this tutorial we’ll integrate Uppy with Pintura Image Editor to visually optimise and compress images before they’re uploaded to the server. Compressing and cropping images before they’re send to the server can save bandwidth, save manual cropping work, and allows the user to have more control over their own content. Use the techniques described in this article to enable your users to edit…

Resize Images Proportionally While Keeping The Aspect Ratio

Sometimes images are just too big to display on the web page. We don’t need JavaScript to fix this. We can resize images proportionally with HTML image tags or CSS background styles. Let’s look at the different options we have to size images while keeping their aspect ratio in check. Resizing HTML image tags Our first choice is to set only one size property, either width or height , the browser…

Edit Images Before Uploading Them To Your WordPress Media Library

In this short tutorial we’ll use a custom <pintura-input> element to add image editing and uploading to any WordPress website front-end. Let’s take a look below at what we’re building. Select a file to start editing, click done and the file will be uploaded. The image edit functionality and custom field are provided by Pintura Image Editor . For privacy reasons the file upload in this demo is…

TypeScript Interface Merging And Extending Modules

FilePond is split up in a core library and a wide range of plugins. The plugins add properties to the core. But how do we extend the core TypeScript Interface to show the plugin properties? Let’s take a look. We have a core library, in this case FilePond , and we have a plugin that dynamically adds a property called allowFilePoster to the core instance. import { create } from 'filepond' ; import…

Convert A Blob To A File Using JavaScript

Sometimes you get a Blob object when instead you would like to have a File. For example, when you use blob() on a fetch response object. In this quick tutorial we’ll explore how to turn a Blob into a File. Fetch The script below converts a fetch response into a Blob . fetch ( './image.jpeg' ) . then ( ( res ) => res . blob ( ) ) . then ( ( myBlob ) => { console . log ( myBlob ) ; // logs: Blob {…

How To Prompt The User To Download A File

Sometimes we just want to download an image file instead of opening it in the browser. For these situations we can use the download attribute. In this article we’ll learn how to use it and how we can automate its behavior with JavaScript. The download attribute tells the browser to download a link target when it’s clicked. < a href = " /media/cat.jpeg " download > cat.jpeg </ a > Try it here:…

Convert A File To A Base64 String Or DataURL Using JavaScript

Converting JavaScript file objects or blobs to Base64 strings can be useful. For example when we can only send string based data to the server. In this tutorial we’ll explore how to use JavaScript to generate a Base64 string and a DataURL from a file object. In both examples we’ll use a file obtained from a file input field. Encoding a File as a DataURL We use FileReader to convert the file object…

Applying A Circular Crop Mask To An Image

Profile pictures are often masked by a circle. How can we present our images in such a circle. Lets explore two options, one where we use CSS and one where we actually mask the image data. Applying the mask using CSS Applying a circular mask to an image using CSS is quite straightforward. We only have to set the border-radius property and we’re done. < style > img { border-radius : 50% ; } </…

Drawing Decorative Lines With CSS

In this short article we’ll explore drawing decorative lines with CSS using Pseudo Elements, Background Images, and SVG. After reading you’ll have learned a couple of interesting techniques for drawing section separators or other decorative line elements with CSS. Pseudo elements We can generate a pseudo-element using the ::before or ::after selectors. This adds a new child to our targeted element…

Pintura Image Editor Lifetime Hobby License Giveaway

I want to start 2021 with a positive vibe so I’m joining Zell Liews JavaScript course giveaway. I’m giving away 5 Lifetime Pintura Image Editor Hobby licenses . The usual price for the Hobby license subscription is $149 yearly. Not familiar with Pintura Image Editor? You can find a demo here Zell is giving away 10 copies of his fantastic Learn JavaScript course , this course normally costs $495.…

Applying Watermarks To Images With FilePond

Watermarking photos can be a tedious task. In this quick tutorial we’ll use FilePond and the FilePond Image Transform Plugin to automatically add watermarks to images. FilePond is free and is compatible with most popular frameworks, you can use the result of this tutorial in your React , Vue , Svelte , Angular , or jQuery projects. If you’re in a rush and want to skip to the result, you can play…

Cross-Browser Alignment Of The Canvas FillText Draw Call

If we use the HTML5 canvas fillText API and compare output from various browsers we see that the draw offset differs slightly. In this quick tutorial we’ll use a snippet to determine this offset and then correct the draw position. Differences The article banner is just an impression, but reality is not far off. We can see the actual difference in draw offset below, it’s just a few pixels, but it’s…

Blocking Navigation Gestures On iOS Safari

iOS Safari 13.4+ allows us to block back and forward navigation gestures. Super useful for media galleries and image croppers where users interact with elements on the side of the viewport and most likely don’t want to navigate to another page. Let’s take a minute and look at the code snippet. The only thing we need to do is prevent the default action of the "touchstart" event. We can do this with…