undefined
undefined

Reputation: 6864

JS prevent flickered input border on focus

I'm trying to build a custom input number. The only problem I have is that when I click on the button multiple times (increment), I'm getting a flickered input border.

const input = document.querySelector('input');
document.querySelector('button').addEventListener('click', () => {
	input.focus();
	const value = input.value ? parseFloat(input.value) : 0;
	input.value = value + 1;
})
body {
	margin: 50px;
}

* {
	box-sizing: border-box;
}

input:focus {
	border: 1px solid red;
	outline: none;
}
<input type="text">

<button>Increment</button>

There is a way to getting around it?

Upvotes: 0

Views: 50

Answers (4)

Hiren Vaghasiya
Hiren Vaghasiya

Reputation: 5544

Just change border and padding for input

const input = document.querySelector('input');
document.querySelector('button').addEventListener('click', () => {
	input.focus();
	const value = input.value ? parseFloat(input.value) : 0;
	input.value = value + 1;
})
body {
	margin: 50px;
}

* {
	box-sizing: border-box;
}

input {
  border:1px solid #777777;
  padding:2px 0px;
}


input:focus {
  border:1px solid red;
  outline: none;
}
<input type="text">

<button>Increment</button>

Upvotes: 0

rlemon
rlemon

Reputation: 17666

If you reverse the elements you can use the adjacent sibling selector button:active + input to select the input styles while the button is being pressed. However to re-align things you will need to use a container and grid (or I'm sure you can pull this off with flex or just floats)

CSS Grid: https://developer.mozilla.org/en-US/docs/Web/CSS/grid

Adjacent Sibling Selector: https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator

const input = document.querySelector('input');
document.querySelector('button').addEventListener('click', () => {
	input.focus();
	const value = input.value ? parseFloat(input.value) : 0;
	input.value = value + 1;
})
body {
	margin: 50px;
}

* {
	box-sizing: border-box;
}

button:active + input, 
input:focus {
	border: 1px solid red;
	outline: none;
}

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.container input {
  order: 1;
}
.container button {
  order: 2;
}
<div class='container'>
  <button>Increment</button>
  <input type="text">
</div>

Upvotes: 0

Will Jenkins
Will Jenkins

Reputation: 9787

The problem is that your button is taking focus when it is clicked. To prevent this happening, you can intercept the mousedown event on your button and call preventDefault().

However, forcing focus like this is a strange thing to do and best avoided.

const input = document.querySelector('input');

const buttonEl = document.querySelector('button');
buttonEl.addEventListener('mousedown', ev => ev.preventDefault()) 
buttonEl.addEventListener('click', () => {
	input.focus();
	const value = input.value ? parseFloat(input.value) : 0;
	input.value = value + 1;
})
body {
	margin: 50px;
}

* {
	box-sizing: border-box;
}

input:focus, input:active {
	border: 1px solid red;
	outline: none;
}
<input type="text">

<button>Increment</button>

Upvotes: 1

Nicolae Maties
Nicolae Maties

Reputation: 2675

const input = document.querySelector('input');
document.querySelector('button').addEventListener('click', () => {
	input.focus();
	const value = input.value ? parseFloat(input.value) : 0;
	input.value = value + 1;
})
body {
	margin: 50px;
}

* {
	box-sizing: border-box;
}

input {
  border: 1px solid red;
	outline: none;
}

input:focus {
	border: 1px solid red;
	outline: none;
}
<input type="text">

<button>Increment</button>

Upvotes: 0

Related Questions