Sketch the borders of the element (animated)

Seeking a way to create a button with an animated border that looks like it is being drawn.

Current progress involves some code, but it's not working smoothly with border-radius set. (keep an eye on the corners)

https://codepen.io/anon/pen/MbWagQ

<button class="draw">draw</button>

//Colors
$cyan: #60daaa;
$red: #f45e61;

// Basic styles
button {
  background: none;
  border: 0;
  box-sizing: border-box;
  color: $red;
  font-size: inherit;
  font-weight: 700;
  padding: 1em 2em;
  text-align: center;
  margin: 20px;

  // Necessary for pseudo-elements absolute positioning
  position: relative;
  vertical-align: middle;

  &::before,
  &::after {
    box-sizing: border-box;
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
  }
}

.draw {
    transition: color 0.25s;
    border-radius: 7px;

  &::before,
  &::after {
    border-radius: 7px;
    border: 3px solid transparent; 
    width: 0;
    height: 0;
  }

  // Top & right borders expanding effect
  &::before {
    top: 0;
    left: 0;
  }

  // Bottom & left borders expanding effect
  &::after {
    bottom: 0;
    right: 0;
  }

  &:hover {
    color: $cyan;
  }

  // Hover effects
  &:hover::before,
  &:hover::after {
    width: 100%;
    height: 100%;
  }

  &:hover::before {
    border-top-color: $cyan; 
    border-right-color: $cyan;
    transition:
      width 0.25s ease-out, 
      height 0.25s ease-out 0.25s; 
  }

  &:hover::after {
    border-bottom-color: $cyan; 
    border-left-color: $cyan;
    transition:
      border-color 0s ease-out 0.5s, 
      width 0.25s ease-out 0.5s, 
      height 0.25s ease-out 0.75s; 
  }
}

Preferably looking to achieve this effect using only HTML and CSS, avoiding SVG files if possible. JavaScript could be considered as well.

Answer №1

It appears that the issue lies in the initial height of your draw::before/draw::after elements being set to 0px during the transition, causing the border radius to appear distorted.

button {
  background: none;
  border: 0;
  box-sizing: border-box;
  color: #f45e61;
  font-size: inherit;
  font-weight: 700;
  padding: 200px;
  text-align: center;
  margin: 20px;
  position: relative;
  vertical-align: middle;
}
button::before,
button::after {
  box-sizing: border-box;
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
}
.draw {
  -webkit-transition: color 0.25s;
  transition: color 0.25s;
  border-radius: 70px;
}
.draw::before,
.draw::after {
  border-radius: 70px;
  border: 30px solid transparent;
  width: 0;
  height: 0;
}
.draw::before {
  top: 0;
  left: 0;
}
.draw::after {
  bottom: 0;
  right: 0;
}
.draw:hover {
  color: #60daaa;
}
.draw:hover::before,
.draw:hover::after {
  width: 100%;
  height: 100%;
}
.draw:hover::before {
  border-top-color: #60daaa;
  border-right-color: #60daaa;
  -webkit-transition: width 1.25s ease-out, height 1.25s ease-out 1.25s;
  transition: width 1.25s ease-out, height 1.25s ease-out 1.25s;
}
.draw:hover::after {
  border-bottom-color: #60daaa;
  border-left-color: #60daaa;
  -webkit-transition: border-color 0s ease-out 2.5s, width 1.25s ease-out 2.5s, height 1.25s ease-out 3.75s;
  transition: border-color 0s ease-out 2.5s, width 1.25s ease-out 2.5s, height 1.25s ease-out 3.75s;
}
<h1>CSS Border Transitions</h1>
<button class="draw">draw</button>

By adjusting the animation speed and size, you can better visualize the problem. It might be beneficial to include a transition for the right/left border during the height transformation to prevent any unusual shapes at the 'drawing point.'

For a clearer example of the skewed border radius, please refer to this image:

http://codepen.io/anon/pen/mOdOyQ

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

broadcast a video file from a Node.js server to multiple HTML5 clients at the same time

After researching online, I have been looking for a way to simultaneously stream a video.mp4 to multiple html5 clients. Despite reading various tutorials, I haven't found the ideal solution using nodejs. Do you have any suggestions or alternative met ...

Sibling selector beside not functional

Trying to create a sliding sidebar without using JavaScript has presented me with a challenge involving an adjacent sibling selector that just won't function as expected. Here is the code snippet causing the issue: .sidebar { position: fixed; ...

Display of certain special characters such as ">" may be affected when using UTF-8 encoding

Here are the codes I'm working with: ul.pathnav a:before{ content:"\0X3E"; text-decoration:none; } I have been trying to use the hex code \0x3e for ">", but it doesn't seem to be working. However, when I tried using ...

Using JSON within HTML: A guide to sanitizing stringified objects

Is there a way to improve the readability of a string that looks like an object but is actually just a string? It currently does not look very nice and easy to read. Using JSON.parse doesn't work because not every element in the string meets the requi ...

Modify the content of a div by clicking on a word or link using Javascript

I'm attempting to create a clickable word (page 2) that acts as a link to display different div content. When the user selects option 2 and clicks the next button, they should be able to click the "Page 2" text to show the content with id="test1" (Cho ...

Dynamically assigning column values based on object properties

I am currently utilizing the Ionic Framework along with its grid system that is reminiscent of Bootstrap. However, I believe my query leans more towards AngularJS than specific Ionic components. Here is what I have: <ion-col *ngFor="let col of row ...

Incorporate the key as a prop within a Child Component in a React application

I am trying to display a list of elements in React, where the key of each element is used as an index in front of the item. However, when I try to access props.key, it just returns undefined. Does anyone have any suggestions on how to access the key proper ...

Troubleshooting Dynamic Input Issue - Incorrect Appending Behaviour - Image Attached

I am working on a project that involves adding input fields dynamically using JavaScript. However, I've encountered an issue where the styling of the first input field is not applied correctly when it is clicked for the first time. You can see the dif ...

transferring a variable that has already been utilized through ajax

I have implemented a jquery datepicker on my webpage. Next to the datepicker, there is a section that displays events when you hover over a date. I was able to successfully get the date into the header of this section. However, I am struggling with transfe ...

The CSS media query isn't functioning properly on Safari browser

Currently, I am working on a project using React JS and CSS. In order to make it responsive, I have implemented media queries. However, I have encountered an issue where the media query is not functioning properly in Safari browsers on both phones and PC ...

Error receiving by React while updating an array with setState() in TypeScript

I am in search of a way to adjust a property of an item within an array by using the updater returned from setState. The function is passed down as props to the child, who then invokes it with their own index to update their status. const attemptToUpdate ...

Sending a JavaScript array to a Struts action with jQuery Ajax: A comprehensive guide

I'm a beginner with Struts 2 and I'm trying to pass a JavaScript array to a Struts action class using jQuery AJAX. The alert message is displaying correctly, but the execute() method is not functioning as expected. When I include System.ou ...

Preventing the $_POST action value from being altered to match the ajax page path

My current setup involves using php, jquery, and ajax to update a particular section. The ajax call is executed successfully, but I encounter an issue where the global $_SERVER[SCRIPT_NAME] changes to match the ajax path when the requested data is returned ...

"Using HTML to assign a unique identifier to an image within

Apologies in advance for any errors as I am relatively new to html. I am attempting to construct a table with images that have onclick events, so that each clicked seat is tracked and its id is added to a list to change the class. Each image has been give ...

What is the process for including a task in the current method?

I've been working on building a web app similar to Google Calendar. I have successfully created the necessary objects and methods, but now I need to implement a feature that allows users to add tasks. My current idea is for users to input a task which ...

Setting the default selection in AngularJS based on the URL entered

I've encountered an issue with a dropdown menu in my AngularJS version 1.4 application. The dropdown menu contains links to different sections of the page. The problem arises when I directly enter the page URL - instead of selecting the correct link f ...

The Vue router-view is mistakenly loading the parent component instead of displaying its own content

Here is a simple route configuration: { path: '/', component: Home, }, This route configuration sets the path to the home page and loads the Home component when the path is '/'. However, I am encountering an issue where the Po ...

Creating a personalized context menu in Javascript: The ultimate guide to incorporating copy and paste features

We are developing a unique context menu for our online text editor, complete with copy/paste options. However, we encountered difficulties accessing the system clipboard from within the browser. It once seemed impossible to achieve this, as discussed in th ...

Deleting validation messages from my MVC controls

I set up some validation in my Model by adding the following code: [Required] [StringLength(60, MinimumLength = 4)] [Display(Name = "Users code")] public string UserCode { get; set; } When c ...

Rephrase the ajax call and the data retrieved

I'm struggling to find a solution for writing this code snippet without using async: false,. var imageX; var groupX; $.ajax({ type:'GET', url:'php/myphp.php', dataType:'json', async: false, success: ...