<div class="layout">
  <!-- ここからボタンのHTML -->
  
  <div class="button">
    <a href="#">ボタン<span></span></a>
  </div>
  
  <!-- ここまでボタンのHTML -->
</div>
/* ここはレイアウトなのでボタンとは関係ない */
* {
  margin: 0;
}

.layout {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 50px;
  width: 100%;
  height: 100vh;
}

/* ここからボタンのCSS */
.button {
	a {
		position: relative;
		display: flex;
		justify-content: center;
		align-items: center;
		width: 240px;
		height: 50px;
		font-size: 16px;
		text-decoration: none;
		color: #5cc0ef;
		border: 1px solid #5cc0ef;
		overflow: hidden;
		transition: all 0.5s;

		span {
			position: absolute;
			display: block;
			width: 0;
			height: 0;
			border-radius: 50%;
			background-color: #5cc0ef;
			transition: width 0.4s ease-in-out, height 0.4s ease-in-out;
			transform: translate(-50%, -50%);
			z-index: -1;
		}

		&:hover {
			color: #fff;

			span {
				//ボタンの横幅×2
				width: calc(240px * 2);
				height: calc(240px * 2);
			}
		}
	}
}
View Compiled
document.addEventListener("DOMContentLoaded", function() {
  const buttons = document.querySelectorAll('.button');

  buttons.forEach(function(button) {
    button.addEventListener('mouseenter', function(e) {
      const rect = button.getBoundingClientRect();
      const relX = e.pageX - rect.left - window.scrollX;
      const relY = e.pageY - rect.top - window.scrollY;
      const span = button.querySelector('span');
      if (span) {
        span.style.top = relY + 'px';
        span.style.left = relX + 'px';
      }
    });

    button.addEventListener('mouseout', function(e) {
      const rect = button.getBoundingClientRect();
      const relX = e.pageX - rect.left - window.scrollX;
      const relY = e.pageY - rect.top - window.scrollY;
      const span = button.querySelector('span');
      if (span) {
        span.style.top = relY + 'px';
        span.style.left = relX + 'px';
      }
    });
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.