Home > Net >  How to apply box shadow on a div when input element inside it is focused
How to apply box shadow on a div when input element inside it is focused

Time:08-11

So I have created a custom input element with increment and decrement button inside a parent div. I want to apply a box shadow on the parent div when the input element is in focus and not when the increment and decrement arrow are clicked. Code is something like

<div className='parent'>
   <input type='number' onChange={onChange}>
   <div className='arrow-btns'>
       <Increment/>
       <Decrement/>
   </div>
</div>

CodePudding user response:

You can use focus and blur event on the input, and add and remove the placeholder class which apply the box shadow on the parent by input.parentNode.classList.add('placeholder') and input.parentNode.classList.remove('placeholder')

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

input.addEventListener('focus', () => {
  input.parentNode.classList.add('placeholder')
})

input.addEventListener('blur', () => {
  input.parentNode.classList.remove('placeholder')
})
.placeholder {
    box-shadow: 2px 3px #888888;

}
<div className='parent'>
   <input id="input" type='number' onChange={onChange}>
   <div className='arrow-btns'>
       <Increment/>
       <Decrement/>
   </div>
</div>

CodePudding user response:

You can use the :has selector.

.parent:has(input:focus) {
  -webkit-box-shadow: -4px 7px 31px 25px rgba(0,0,0,0.14);
  -moz-box-shadow: -4px 7px 31px 25px rgba(0,0,0,0.14);
  box-shadow: -4px 7px 31px 25px rgba(0,0,0,0.14);
}

Please note that few browsers are yet to support it and once they do, this'll be a simple solution for your use case. You can read more about it here.

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

CodePudding user response:

For a pure React based solution, you can:

  1. Create a boolean state focused that represents whether the input is focused or not
  2. Make a style object with box shadow that's set based on that state
  3. Set that style for the parent
  4. Use onFocus and onBlur events on the input to set the state

Since we used a state, the component will re-render when it's changed, so it'll set the box shadow value accordingly:

const { useState } = React;

const Increment = () => <button>Increment</button>
const Decrement = () => <button>Decrement</button>

function App() {
   const [focused, setFocused] = useState(false);
   
   const style = {
     width: '200px',
     height: '90px',
     boxShadow: focused? '0 0 5px rgba(0,0,0,0.5)' : 'none'
   }
   
   const setToFocused = () => setFocused(true);
   const setToUnfocused = () => setFocused(false);
   
  return (
    <div className='parent' style={style}>
      <input type='number' onFocus={setToFocused} onBlur={setToUnfocused}></input>
        <Increment/>
        <Decrement/>
   </div>
  )
}


ReactDOM.render(
  <App />,
  document.getElementById('root')
)
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<div id="root"></div>

It's also good to separate the intents of the style objects, where one is the base style and the other depends on the state. Then just merge them:

const { useState } = React;

const Increment = () => <button>Increment</button>
const Decrement = () => <button>Decrement</button>

function App() {
   const [focused, setFocused] = useState(false);
   
   const baseStyle = {
     width: '200px',
     height: '90px'
   }
   
   const focusedStyle = focused 
   ? { boxShadow: '0 0 5px rgba(0,0,0,0.5)' } 
   : {}
   
   const style = {...baseStyle, ...focusedStyle}
   
   const setToFocused = () => setFocused(true);
   const setToUnfocused = () => setFocused(false);
   
  return (
    <div className='parent' style={style}>
      <input type='number' onFocus={setToFocused} onBlur={setToUnfocused}></input>
        <Increment/>
        <Decrement/>
   </div>
  )
}


ReactDOM.render(
  <App />,
  document.getElementById('root')
)
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<div id="root"></div>

  • Related