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…
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)…
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…
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…
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…
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…
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…
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…
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…
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 ) .…
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…
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…
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...…
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…
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…
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…
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…
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…
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…
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…
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…
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 =…
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…
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…
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…
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.…
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…
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…
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?…
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…
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…
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…
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…
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…
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.…
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…
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,…
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…
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…
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…
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…
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 {…
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:…
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…
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% ; } </…
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…
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.…
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…
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…
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…