Can a CSS responsive spinner have a border width that adjusts dynamically based on the parent element?

Recently, I've been working on creating a simple spinner class that can easily be added to any element, whether it's a small button or an entire page.

Despite exploring viewport values, I have yet to discover a method for achieving a relative border-width.

  • If a relative border-width isn't feasible, one solution could involve dividing the loading process into three classes: small, medium, and large. However, this approach introduces additional complexity.
  • Is there a way to utilize media queries based on the parent element width rather than the device width? This adjustment might provide a potential solution.
  • Alternatively, is there a CSS-only spinner type that doesn't rely on border-width and can be implemented as an ::after element?

The essential criteria for testing the spinner are:

  1. Appealing appearance when applied to the entire page
  2. Attractive display when added to a small button
  3. Compatibility with mobile devices
  4. Ease of application by simply adding a class without altering the existing content
  5. No reliance on JavaScript

I'm open to suggestions for a more visually appealing loader, given my limited expertise in CSS. Any guidance would be greatly appreciated.

Fiddle : http://jsfiddle.net/ppgab/adfnc5tk/6/

Here's the code I have developed so far :

/*Spinner with overlay and no mouse events*/
@keyframes spinner {
    to {transform: rotate(360deg);}
}
.loading::before {
    position:absolute;
    content : '';
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: gray;
    z-index: 2;
    opacity: 0.65;
}
.loading:after {
    content: '';
    box-sizing: border-box;
    position: absolute;
    top: 50%;
    left: 50%;
    width: 25%;
    /*! height: 5rem; */
    margin-top: -12.5%;
    margin-left: -12.5%;
    border-radius: 50%;
    border: solid transparent;
    border-top-color: #07d;
    border-bottom-color: #07d;
    animation: spinner .8s ease infinite;
    z-index:3;
    padding-top: calc(12.5% - 1em);
    border-width: 1em;
    padding-bottom: calc(12.5% - 1em);
}
.loading {
    pointer-events: none;
    cursor: wait;
}

.text-center {
  text-align:center;
}

Answer №1

For a dynamic border-width, using SVG would be ideal, where the border is represented as a stroke.

/*Spinner with overlay and no mouse events*/
@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
.loading::before {
  position: absolute;
  content: "";
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: gray;
  z-index: 2;
  opacity: 0.65;
}

.loading {
  pointer-events: none;
  cursor: wait;
}

.text-center {
  text-align: center;
}

svg {
  z-index: 2;
  width: 40vmin;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  animation: spinner .8s ease infinite;
}
<div class="loading text-center">
<h1>
  Resize this window to see it in action !
</h1>
<h3>
But if you reduce the width too much it gets ugly :(
</h3>
<button>
 You can't click me!
</button>

</div>
  <svg viewBox="-50 -50 100 100">
    <circle r="46" fill="none" stroke="#07d" stroke-width="7" stroke-dasharray="72.26" stroke-dashoffset="-36.13" />
  </svg>

In the CSS, I've specified width:40vmin;, but adjustments may be needed if applying it on a button element.

Answer №2

Utilizing some less mainstream properties such as conical-gradient and mask-image, achieving this effect is feasible.

Optimized for Chrome browser (most likely).

body {
  background: lightgreen;
}

div.conic-gradient {
  width: 200px;
  height: 200px;
  margin: 1em auto;
  position: relative;
  border: 1px solid grey;
}

.conic-gradient:after {
  content: "";
  background: conic-gradient(
    blue 25%,
    transparent 0 50%,
    blue 0 75%,
    transparent 75%
  );
  border-radius: 50%;
  -webkit-mask-image: radial-gradient(transparent 50%, rgba(0, 0, 0, 1) 50%);
  background-size: cover;
  width: 100px;
  height: 100px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  position: absolute;
  animation: spinner 2s linear infinite;
}

@keyframes spinner {
  0% {
    transform: translate(-50%, -50%) rotate(0deg);
  }

  100% {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}
<div class="conic-gradient"></div>

Answer №3

You have the option to adjust the spinner size by using the font size property and inheriting it from the parent element;

.loading {
  box-sizing: border-box;
  clear: both;
  font-size: 1rem;
  position: relative;
}

.loading:after {
  animation: spinAround .5s infinite linear;
  border: 2px solid #dbdbdb;
  border-radius: 290486px;
  border-right-color: transparent;
  border-top-color: transparent;
  content: "";
  display: inline-flex;
  height: 1em;
  width: 1em;
}

.loading:after {
  position: absolute !important;
  z-index: 4;
}

.loading:after {
    font-size: inherit;
}

@keyframes spinAround {
  from {
    transform: rotate(0)
  }
  to {
    transform: rotate(359deg)
  }
}
<div class="loading">
Resize this window to see it in action!
</div>

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

Utilize the Step Function in Jquery to create animated rotation at a specific degree angle

I have a div that is currently rotated at -35 degrees (as set in the CSS file). I would like to be able to click on it so that it rotates back to 0 degrees. Here is the code from my Javascript file: $("div#words").on("click",function(e){ $(this).anim ...

My carousel navigation buttons are unresponsive in Bootstrap 4

Here's my code. I'm attempting to create an image carousel with button controls, but the images are not transitioning smoothly as intended. Additionally, the buttons seem to be unresponsive. <div class="carousel slide" id="cservices" data-ri ...

Element not found: {"method":"xpath","selector":"//*[@id='content container']

The error is occurring despite having the correct xpath in the code: Unable to locate element: {"method":"xpath","selector":"//*[@id='content column']... It seems like there might be multiple xpaths in the field. Here is the code snippet: dr ...

Opacity of the background in React CSS

I'm having trouble getting the background of my CSS to have opacity without affecting the navbar. I've tried adjusting the body tag in CSS, but the navbar keeps taking on the opacity instead of the background. Is there a way to fix this issue? ...

How to Use Absolute Positioning in Bootstrap 3.0 to Position Child Divs

I have a div block that needs to always be displayed at the bottom of the section, regardless of whether the section above is empty. The inner div should stay at the bottom of the section, as shown in the attached image. https://i.sstatic.net/cor6k.jpg T ...

Issues with scrolling, styling in css, and Vue challenges

I'm a beginner in this topic, currently working with Vue and CSS. I've managed to create a responsive menu, but I'm facing difficulty in implementing scroll only for the drop-down menu. The issue I'm encountering is that when I scroll, ...

What is the protocol for displaying linear gradients that overlap?

My objective is to create a unique cutting corner effect using linear gradients. Achieving this on one corner is straightforward: body { background: #eac996; } .box { width: 100px; height: 100px; margin: 100px auto; padding: 20px; backgroun ...

Having trouble customizing the HTML range input?

I am looking to customize the appearance of a range input slider. Specifically, I want the slider to be green for the lower portion (where the thumb has moved) and grey for the remaining section. I have successfully changed the default styles from blue and ...

Deleting an unclosed HTML comment using PHP

I am currently working on a PHP script to display a chat log. The chat log may contain user input, including HTML tags. My main concern is preventing any <!-- entered by the user from causing my entire file to be commented out. Unfortunately, my curren ...

"Utilizing Bootstrap 5 to create a responsive layout with five equal columns specifically designed for

After some revision, I have improved the clarity of my question. As I understand, Bootstrap divides the screen into 12 columns and allows you to use classes like col-md- or col-lg- to adjust layout for different screen sizes. My question is: Is there a wa ...

The functionality of an Ajax call is limited to a single use, regardless of using

For the past couple of weeks, I've been struggling to get my Ajax call to function more than once. As a self-taught individual, I've been trying my best to troubleshoot this issue on my own, but it's really getting to me. Some others facing ...

Having difficulty accessing the ::after element on Firefox when attempting to click

I've encountered an issue with my HTML and CSS code - it functions perfectly on Chrome, yet behaves differently on Firefox. button#groupToggle { background: 0 0; border: 1px solid #e6e6ed; color: #222; float: none; margin: 0 0 ...

Fetching data from local JSON file is being initiated twice

I need some help understanding why my code is downloading two copies of a locally generated JSON file. Here is the code snippet in question: function downloadJson(data, name) { let dataStr = 'data:text/json;charset=utf-8,' + encodeURICompo ...

Converting CSS code into JavaScript

I am currently working with the following code: .mr15 > * margin-right: 15px &:last-child margin-right: 0 I need help translating this code to Javascript. Should I use JQuery or pure Javascript for this scenario? Thank you. ...

Transforming the playbackRate property of a web audio-enabled audio element

I recently experimented with integrating an audio element into the web audio API using createMediaElementSource and achieved success. However, I encountered an issue when attempting to change the playback rate of the audio tag. Despite trying multiple appr ...

Adjust the size of a large column to fit into a smaller one using Bootstrap or vanilla CSS

I've experimented with various methods and it seems like achieving this without JS might not be possible - but before I throw in the towel, I wanted to reach out for help here. I have a lengthy navigation div on the left side and a column of dynamic ...

Creating a customizable theme for a website built with Bootstrap, incorporating changes to brand colors and more, by utilizing a .less file

I have built my asp site using bootstrap as the client-side CSS framework. I am currently working on implementing a feature that allows users to customize their site's brand color and other aspects, with these changes being saved permanently. While I ...

Obtain the information sent by the Jquery ajax call

Below is the code snippet in question: $.ajax({ type: 'GET', data: { s: sToSearch }, url: 'http://localhost:9809/handlers/search.ashx', }).done(function (d) { sCache[sToSearch.toLowerCase()] = d; showResult(d); }); ...

How should we measure the string as if it were in HTML?

I have the exact string : 123.. I am curious to know what its length would be as a SPAN element on an HTML page. font-name:arial font-size:16px; I decided to conduct an experiment: http://jsbin.com/axezib/edit#preview This resulted in: <span style ...

How to modify the color of a div element with jQuery?

I need some help changing the color of a div with 'jQuery', but I am not sure how to do it. Below is the code I have been trying: function updateDivColor() { $('#OutlineX1').css("color","blue"); } ...