Cloudinary Studio | CSS-Tricks
Strategy

Cloudinary Studio | CSS-Tricks


I knew that Cloudinary worked with video as well as images but, the other day, I was curious if Cloudinary offered a video player embed just like other video hosts do (e.g. YouTube, Vimeo, etc). Like an <iframe> that comes with a special player.

I was curious because, as much as I appreciate the simplicity of just tossing a <video> on a page, there is one little hurdle that I always forget: you have to use a poster attribute if you want anything but a blank white rectangle on mobile browsers. Having to cut a special poster for every video I use is a step I’m frankly just too lazy to do most of the time.

Turns out Cloudinary does a have a player, and it allows for a bunch of nice customization, including handling the poster for you: Video Player Studio.

If I use this player instead, not only do I get a free configurable poster, but other advantages you’d expect from Cloudinary, like serving the video in the best possible format and optimizing the size.

But there is another thing that is a kind of big deal here, particularly for long videos: “adaptive bitrate streaming.” Behind the scenes, some library probably needs to be downloaded, but the bandwidth savings likely pay for that almost instantly. I’m not an expert on any of this by any means, but I’m referring to HLS and MPEG-DASH, which seem to be the big players, and this Cloudinary player offers both.

For the record, this post is not sponsored by Cloudinary. I was just thinking about all this the other day because we frequently embed video here on CSS-Tricks and I already use Cloudinary for all sorts of stuff.

Here’s an example:

In running this past the Cloudinary team, they said two things:

  1. The player is built on top of VideoJS. Credit where credit is due.
  2. They’ve got a blog post that goes far deeper into customizing the player than I talk about here.



Source link

CORS error
Strategy

Packaging a React App With Spring Boot


In this article, we’re going to discuss how to combine Create React App with Spring Boot to give you a single war file, so that we:

  • Can have our frontend and backend in a single war file with optimized productions build
  • And keep the benefits Create React App gives such as hot reloading

Setup

  1. Must have Java installed. Head over here to download a version.
  2. Must have Maven installed. For Mac, I used Homebrew (brew install maven), but otherwise, head here.
  3. Must have Node installed. For Mac, I used Homebrew (brew install node), but otherwise, head over here.

Note: my IDE of choice is IntelliJ. When working on react code, I usually switch over to VS Code. Feel free to use what makes you feel comfortable. 

To get started, create an empty repo on Github and add a ReadMe, gitignore, license, etc. Then, head over to https://start.spring.io to create your Spring application and download it locally. Group and Artifact can also be anything you want them to be.

GroupId: com.react.container;      

Artifact: spring-react-combo-app

Next, unzip the downloaded project into your git directory. Commit, Commit, Commit. Your SpringReactComboAppApplication should look like this:

After we have this taken care of, we can create a basic service. We’ll call it the DadJokesController. This should be created in the same folder as the SpringReactComboAppApplication file. I’m aware this is not a proper REST API format, but let’s ignore that for now. 

In your terminal run 

Then, in your browser check http://localhost:8080/api/dadjokes . You should see the dad joke we added to our controller. 

To create your React app, just run the following in the root directory 

You can call it whatever you want. (I just called mine basic-frontend-app.)

To run the front end application: 

Since we want to integrate our Dad Jokes service into the frontend, first we will address proxy issues. If you’ve noticed, your service starts on localhost:8080 while the frontend starts on localhost:3000. If we try calling our service from the frontend, depending on your browser, you’ll get a CORS error.

CORS error

CORS error

The simplest way to address the issue is to have your frontend proxy any requests from port 3000 to 8080. This change will be made in your package.json file

Add the following to your frontend App.js file.

Restart the frontend, and you should be good. If you happen to get this error, I deleted my package-lock.json file and node_modules folder reinstalled npm packages and ran it again

Proxy config error

Proxy config error

You can now see the results of the dad jokes API call.

Now that our basic frontend and backend are complete, it’s time to create a production build and single war file. 

Under the <dependencies> add this:

Under the <plugins> section of the pom file, we will add the following commands, which will do the following things when mvn clean install is run.

  1. npm install will run with the specified version of Node.
  2. A production build of our frontend will run.
  3. We will deposit the production build.

Note: The order of your plugins is important, so make sure your node/npm install execution is before copying the build file execution.

After adding this, run mvn clean install and verify that the target/classes directory contains both frontend files and java files. And you should be good to go. 

That’s all I’ve got for now. If you would like to take a look at the repo or use it, it can be found here on my Github.



Source link

Performant Expandable Animations: Building Keyframes on the ...
Strategy

Performant Expandable Animations: Building Keyframes on the …


Animations have come a long way, continuously providing developers with better tools. CSS Animations, in particular, have defined the ground floor to solve the majority of uses cases. However, there are some animations that require a little bit more work.

You probably know that animations should run on the composite layer. (I won’t extend myself here, but if you want to know more, check this article.) That means animating transform or opacity properties that don’t trigger layout or paint layers. Animating properties like height and width is a big no-no, as they trigger those layers, which force the browser to recalculate styles.

On top of that, even when animating transform properties, if you want to truly hit 60 FPS animations, you probably should get a little help from JavaScript, using the FLIP technique for extra smoother animations! 

However, the problem of using transform for expandable animations is that the scale function isn’t exactly the same as animating width/height properties. It creates a skewed effect on the content, as all elements get stretched (when scaling up) or squeezed (when scaling down).

So, because of that, my go-to solution has been (and probably still is, for reasons I will detail later), technique #3 from Brandon Smith’s article. This still has a transition on height, but uses Javascript to calculate the content size, and force a transition using requestAnimationFrame. At OutSystems, we actually used this to build the animation for the OutSystems UI Accordion Pattern.

Generating keyframes with JavaScript

Recently, I stumbled on another great article from Paul Lewis, that details a new solution for expanding and collapsing animations, which motivated me to write this article and spread this technique around.

Using his words, the main idea consists of generating dynamic keyframes, stepping…

[…] from 0 to 100 and calculate what scale values would be needed for the element and its contents. These can then be boiled down to a string, which can be injected into the page as a style element. 

To achieve this, there are three main steps.

Step 1: Calculate the start and end states

We need to calculate the correct scale value for both states. That means we use getBoundingClientRect() on the element that will serve as a proxy for the start state, and divide it with the value from the end state. It should be something like this:

function calculateStartScale () {
  const start= startElement.getBoundingClientRect();
  const end= endElement.getBoundingClientRect();
  return {
    x: start.width / end.width,
    y: start.height / end.height
  };
}

Step 2: Generate the Keyframes

Now, we need to run a for loop, using the number of frames needed as the length. (It shouldn’t really be less than 60 to ensure a smooth animation.) Then, in each iteration, we calculate the correct easing value, using an ease function:

function ease (v, pow=4) {
  return 1 - Math.pow(1 - v, pow);
}

let easedStep = ease(i / frame);

With that value, we’ll get the scale of the element on the current step, using the following math:

const xScale = x + (1 - x) * easedStep;
const yScale = y + (1 - y) * easedStep;

And then we add the step to the animation string:

animation += `${step}% {
  transform: scale(${xScale}, ${yScale});
}`;

To avoid the content to get stretched/ skewed, we should perform a counter animation on it, using the inverted values:

const invXScale = 1 / xScale;
const invYScale = 1 / yScale;

inverseAnimation += `${step}% {
  transform: scale(${invXScale}, ${invYScale});
}`;

Finally, we can return the completed animations, or directly inject them in a newly created style tag.

Step 3: Enable the CSS animations 

On the CSS side of things, we need to enable the animations on the correct elements:

.element--expanded {
  animation-name: animation;
  animation-duration: 300ms;
  animation-timing-function: step-end;
}

.element-contents--expanded {
  animation-name: inverseAnimation ;
  animation-duration: 300ms;
  animation-timing-function: step-end;
}

You can check the example of a Menu from Paul Lewis article, on Codepen (courtesy of Chris Coyer):

Building an expandable section 

After grasping these baseline concepts, I wanted to check if I could apply this technique to a different use case, like a expandable section.

We only need to animate the height in this case, specifically on the function to calculate scales. We’re getting the Y value from the section title, to serve as the collapsed state, and the whole section to represent the expanded state:

    _calculateScales () {
      var collapsed = this._sectionItemTitle.getBoundingClientRect();
      var expanded = this._section.getBoundingClientRect();
      
      // create css variable with collapsed height, to apply on the wrapper
      this._sectionWrapper.style.setProperty('--title-height', collapsed.height + 'px');

      this._collapsed = {
        y: collapsed.height / expanded.height
      }
    }

Since we want the expanded section to have absolute positioning (in order to avoid it taking space when in a collapsed state), we are setting the CSS variable for it with the collapsed height, applied on the wrapper. That will be the only element with relative positioning.

Next comes the function to create the keyframes: _createEaseAnimations(). This doesn’t differ much from what was explained above. For this use case, we actually need to create four animations:

  1. The animation to expand the wrapper
  2. The counter-expand animation on the content
  3. The animation to collapse the wrapper
  4. The counter-collapse animation on the content

We follow the same approach as before, running a for loop with a length of 60 (to get a smooth 60 FPS animation), and create a keyframe percentage, based on the eased step. Then, we push it to the final animations strings:

outerAnimation.push(`
  ${percentage}% {
    transform: scaleY(${yScale});
  }`);
  
innerAnimation.push(`
  ${percentage}% {
    transform: scaleY(${invScaleY});
  }`);

We start by creating a style tag to hold the finished animations. As this is built as a constructor, to be able to easily add multiple patterns, we want to have all these generated animations on the same stylesheet. So, first, we validate if the element exists. If not, we create it and add a meaningful class name. Otherwise, you would end up with a stylesheet for each section expandable, which is not ideal.

 var sectionEase = document.querySelector('.section-animations');
 if (!sectionEase) {
  sectionEase = document.createElement('style');
  sectionEase.classList.add('section-animations');
 }

Speaking of that, you may already be wondering, “Hmm, if we have multiple expandable sections, wouldn’t they still be using the same-named animation, with possibly wrong values for their content?” 

You’re absolutely right! So, to prevent that, we are also generating dynamic animation names. Cool, right?

We make use of the index passed to the constructor from the for loop when making the querySelectorAll('.section') to add a unique element to the name:

var sectionExpandAnimationName = "sectionExpandAnimation" + index;
var sectionExpandContentsAnimationName = "sectionExpandContentsAnimation" + index;

Then we use this name to set a CSS variable on the current expandable section. As this variable is only in this scope, we just need to set the animation to the new variable in the CSS, and each pattern will get its respective animation-name value.

.section.is--expanded {
  animation-name: var(--sectionExpandAnimation);
}

.is--expanded .section-item {
  animation-name: var(--sectionExpandContentsAnimation);
}

.section.is--collapsed {
  animation-name: var(--sectionCollapseAnimation);
}

.is--collapsed .section-item {
  animation-name: var(--sectionCollapseContentsAnimation);
}

The rest of the script is related to adding event listeners, functions to toggle the collapse/expand status and some accessibility improvements.

About the HTML and CSS: it needs a little bit of extra work to make the expandable functionality work. We need an extra wrapper to be the relative element that doesn’t animate. The expandable children have an absolute position so that they don’t occupy space when collapsed.

Remember, since we need to make counter animations, we make it scale full size in order to avoid a skew effect on the content.

.section-item-wrapper {
  min-height: var(--title-height);
  position: relative;
}

.section {
  animation-duration: 300ms;
  animation-timing-function: step-end;
  contain: content;
  left: 0;
  position: absolute;
  top: 0;
  transform-origin: top left;
  will-change: transform;
}

.section-item {
  animation-duration: 300ms;
  animation-timing-function: step-end;
  contain: content;
  transform-origin: top left;
  will-change: transform;  
}

I would like to highlight the importance of the animation-timing-functionproperty. It should be set to linear or step-end to avoid easing between each keyframe.

The will-change property — as you probably know — will enable GPU acceleration for the transform animation for an even smoother experience. And using the contains property, with a value of contents, will help the browser treat the element independently from the rest of the DOM tree, limiting the area before it recalculates the layout, style, paint and size properties.

We use visibility and opacity to hide the content, and stop screen readers to access it, when collapsed.

.section-item-content {
  opacity: 1;
  transition: opacity 500ms ease;
}

.is--collapsed .section-item-content {
  opacity: 0;
  visibility: hidden;
}

And finally, we have our section expandable! Here’s the complete code and demo for you to check:

Performance check

Anytime we work with animations, performance ought to be in the back of our mind. So, let’s use developer tools to check if all this work was worthy, performance-wise. Using the Performance tab (I’m using Chrome DevTools), we can analyze the FPS and the CPU usage, during the animations.

And the results are great!

The higher the green bar, the higher the frames. And there’s no junk either, which would be signed by red sections.

Using the FPS meter tool to check the values at greater detail, we can see that it constantly hits the 60 FPS mark, even with abusive usage.

Final considerations

So, what’s the verdict? Does this replace all other methods? Is this the “Holy Grail” solution?

In my opinion, no. 

But… that’s OK, really! It’s another solution on the list. And, as is true with any other method, it should be analyzed if it’s the best approach for the use-case.

This technique definitely has its merits. As Paul Lewis says, this does take a lot of work to prepare. But, on the flip side, we only need to do it once, when the page loads. During interactions, we are merely toggling classes (and attributes in some cases, for accessibility).

However, this brings some limitations for the UI of the elements. As you could see for the expandable section element, the counter-scale makes it much more reliable for absolute and off-canvas elements, like floating-actions or menus. It’s also difficult to styled borders because it’s using overflow: hidden.

Nevertheless, I think there’s tons of potential with this approach. Let me know what you think!



Source link

Copying text to clipboard
Strategy

How To Copy Text to Clipboard Using Angular 8


Introduction

In this article, we will learn how to copy text to our clipboard and also copy the current date and time, using Angular 8.

Javascript provides a very good feature to copy any text to the clipboard and can paste it anywhere. So in this article, we will copy some text and the current date and time to our clipboard and paste it to a textarea

Prerequisites

  • Basic knowledge of Angular.
  • Visual Studio Code must be installed.
  • Angular CLI must be installed.
  • Node JS must be installed.

Step 1

Let’s create an Angular project, using the following npm command.

Step 2

Open the newly-created project in Visual Studio code and install bootstrap in this project.

Now, open the styles.css file and add a Bootstrap file reference. To add the reference in styles.css file add this line:

Step 3 

Now, let’s create a new component by using the following command:

Step 4

Now, open the copy-clipboard.component.html file and add the following code: 

Step 5

Now, open the copy-clipboard.component.ts file and add the following code:

  

Step 6

Now, open the app.module.ts file and add the following code in this file.

Step 7

Let’s copy the below code and paste it to app.component.html

Step 8 

Now, let’s run the project by using npm start or ng serve command and check the output.

 Copying text to clipboard

Copying current date to clipboard

Copying current time to clipboard

 

Summary

In this article, I have discussed how we can copy any text to the clipboard and paste not only the text, but also the current date and time in Angular 8 applications.

Please give your valuable feedback/comments/questions about this article. Please let me know if you liked and understood this article and how I could improve upon it.



Source link

Post image
Strategy

I’ve build a better mockup finding website UPDATE : webdev


Hey designers! I’m a digital design student. I’ve made better, cleaner, prettier mockup finding experience. Every mockup is handpicked by me and my fellow design students. No ads, no timed redirects, no bullshit. It’s called Malli, (which means model or design).

https://malli.graphics

I’ve processed all feedback I got last time.

I’d love any feedback you guys can give me to make it even better.

Post image



Source link

Thomas with Samson, his cat
Strategy

Hiring My Cat as a Software Developer


Meet Samson. Samson is a cat, more specifically a Faelis Feline. You can see a picture of Samson below. Since it seems to be popular to work from home these days, I figured I’d hire my cat as a software developer. That way, I can lay around in my hammock, enjoying the sun, while my cat does all the heavy lifting. Whenever it’s time to pay salary, all I need to do is to open a box a Whiskas, and voila! Salary paid!

Thomas with Samson, his cat

The idea came from the following logical chain of arguments.

  1. I can’t tell my cat what to do
  2. I can’t tell my software developers what to do
  3. Hence, my cat must be a software developer

Pretty obvious once you think about it, right…?

I am, therefore, looking for more cats to employ, as senior software developers, to create beautiful purrs of software systems that I can sell to my customers so that I can become rich! Muahahahahaha (evil laughter!)

If you are a cat and you are reading this right now, feel free to apply for a job on my team, where Samson will be project lead, and you might be one of the lucky few making the cut, enjoying a life full of lots of purrs and tons of cat food. After all, creating hundreds of thousands of lines of code and beautifully following all lint standards is as simple as clicking a button. Don’t believe me? Realize the following was created by clicking a button, hence I no longer see any needs to employ expensive (human) software developers. 

They’ll only beg for more salary and demand coffee and free pizza when working overtime. Much more financially viable to simply hire a bunch of cats. Below you can watch one of Samson’s teammates working on some Angular and .Net Core-based enterprise applications.

Below you can see one of these software systems that was in fact created by my cat. This particular system is a movie rental database system, based upon MySQL’s Sakila database. However, any database structure can be used for both MS SQL and MySQL to create the end result.

You see, Magic will literally allow you to create a complete .Net Core-based backend and a complete Angular based front by literally clicking a button. This is due to that it reads metadata from your database, which it consumes to create backend CRUD operations towards your database, which it again consumes to create Angular components and services. So even though it will produce about 15.000 lines of code for a database with 80-100 tables, it will do so by having my cat click a simple button, so I figured I no longer need software developers as long as I can teach my cat to click that button. If you can additionally teach your cat how to construct a simple group by SQL statement, extracting a key/value pair from your data, you can even have it create beautiful charts, such as the following illustrates. And even if you can’t teach your cat SQL, you could probably teach it to simply copy and paste SQL example snippets from StackOverflow or something, right …?

The idea was actually conceptualized by taking the observer design pattern to its extreme, to the point where I could create a Turing complete programming language, where each “keyword” in the language was literally loosely coupled together, as simple event sinks. I refer to this process as Super Signals. The programming language I call Hyperlambda. But I suspect its common name will become “Mjau-Lambda” after today for obvious reasons. Below is an example of the code generated for the HTTP GET verb or the “read” operation.

The above will again translate into a valid SQL select statement and automatically transform the results of that select into an array of JSON objects. Below is an example of how it will look in the Angular frontend parts of the equation. This — internally in its Angular component — is tied together using a Material Table that is automatically data-bound, or “reactively” bound if you wish, towards all HTTP REST endpoints created in your Hyperlambda backend. And everything magically happens by simply clicking a button, which I am pretty confident I can teach Samson how to do if I just use positive feedback loops connected to my Whiskas feeding device 🙂

The Sakila system, for instance, contains the same amount of code that a software developer on average would need about 3 months to create according to research in the area. However, Samson created it in 20 seconds. Would it be unfair of me then to invoice my client €20.000? Hmm. Maybe I should avoid getting greedy; better give him a good price. I think I’ll send him a smaller invoice for only €18.000. After all, it’s not like I did any work myself, right …? 😉

Feel free to send me an email if you’re a cat and you’re looking for work, that way I’ll feed you a can of Whiskas per day while invoicing my customers about 40 trillion dollars for the work you do in every single day. Mjaauus and Whiskas for you, dollars for me 🙂

Muhahahahaha (evil laughter 2.0)

Puuh, it’s exhausting clicking that button. Below you can see me and one of my colleagues who’s name is Happy, taking a catnap after an exhausting 5 seconds of work…

By the way, happy April Fools Day 😉



Source link