Home > other >  How to set margin in CSS for SVGIcon based on sibling text position?
How to set margin in CSS for SVGIcon based on sibling text position?

Time:02-25

I want to set margin-left or margin-right for a Icon component inside toggle button component (svg text inside button) in ReactJS using CSS.

MuiButton component with left icon MuiButton component with right icon

Here I want to add space between the icon and button placeholder. Using :first-child and :last-child seems to apply in both scenarios (when icon is on left I want to apply marginRight, when icon is on right I want to apply marginLeft).

How to achieve it in CSS?

CodePudding user response:

You can add an ID attribute to the SVG tag. And only then you will be able to target the SVG in the CSS.

Side note: Since you are using react I will suggest that you create a component for the button itself so it could be re-usable and keep your code clean.

References that might help you out:

MDN Docs: SVG and CSS

MDN Docs: SVG style

#btn-icon{
  /* Indicators to prove it works */
  margin: 0 1rem;
  fill: red;
  /* Indicators to prove it works */
  
  /* Apply your styles here */
  
  /* Apply your styles here */
}
<button>
Placeholder <svg id="btn-icon" focusable="false" aria-hidden="true" viewBox="0 0 24 24">
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM8.5 8c.83 0 1.5.67 1.5 1.5S9.33 11 8.5 11 7 10.33 7 9.5 7.67 8 8.5 8zM12 18c-2.28 0-4.22-1.66-5-4h10c-.78 2.34-2.72 4-5 4zm3.5-7c-.83 0-1.5-.67-1.5-1.5S14.67 8 15.5 8s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></svg>
</button>

CodePudding user response:

If your first code example was correct, you don't have any siblings you could select in css.

Since your buttons text content is not a selectable element in css. Therfore, the svg icon will is both :last-child and :first-child.

You might try to add a js to assign classes to your buttons:

let buttons = document.querySelectorAll('button');
buttons.forEach(function(button, i){
  let icon = button.querySelector('svg');
  let siblingLeft = icon.previousSibling.textContent;
  // strip whitespace
  siblingLeft = siblingLeft.replace(/\s/g, "")
  let btnClass = siblingLeft ?  'icon-right' : 'icon-left';
  button.classList.add(btnClass);
});
body{
  font-size:3em;
}

button{
  font-size:inherit;
  background:#fff;
  border: 1px solid #ccc;
  padding:0.3em;
}

.icon{
  display:inline-block;
  height:1em;
  margin-left:0.3em;
  margin-right:0.3em;
  position:relative;
  bottom:-0.1em;
  fill: green;
}


.icon-right svg{
  margin-right:0
}

.icon-left svg{
  margin-left:0;
  fill:red;
}
<button>
 <svg  focusable="false" aria-hidden="true" viewBox="0 0 24 24">
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM8.5 8c.83 0 1.5.67 1.5 1.5S9.33 11 8.5 11 7 10.33 7 9.5 7.67 8 8.5 8zM12 18c-2.28 0-4.22-1.66-5-4h10c-.78 2.34-2.72 4-5 4zm3.5-7c-.83 0-1.5-.67-1.5-1.5S14.67 8 15.5 8s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" /></svg>Placeholder left
</button>

<button>
Placeholder right<svg  focusable="false" aria-hidden="true" viewBox="0 0 24 24">
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM8.5 8c.83 0 1.5.67 1.5 1.5S9.33 11 8.5 11 7 10.33 7 9.5 7.67 8 8.5 8zM12 18c-2.28 0-4.22-1.66-5-4h10c-.78 2.34-2.72 4-5 4zm3.5-7c-.83 0-1.5-.67-1.5-1.5S14.67 8 15.5 8s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" /></svg>
</button>

But I'm pretty sure your predefined UI css will have some class attributes for different icon types or positionings. (So you should add an accurate code example of your button markup to your question).

  • Related