Creating a scalable button with text and a SVG icon
Hi everyone. I am trying to create a scalable SVG button, that changes the padding around both the text and svg, based on the font-size of the text. Usually I use the css selector below on an anchor tag to create a button that changes padding (specified in em) based on the font-size.
<a className="btn" >Vote</a>
.btn{ display: inline-block; font-size: 1.5rem; padding: 0.75em 1.75em; color: red; background-color: white; border: 2px solid red; font-weight: 700; } I would like to achieve a similar effect, where a change in the font-size (specified in rem) changes the padding around the text and svg proportionally, aswell as the size of the svg. I have attached an image of the scalable button that I am trying to create. Does anyone have any ideas how I might create this?
<a className="btn" >Vote</a>
.btn{ display: inline-block; font-size: 1.5rem; padding: 0.75em 1.75em; color: red; background-color: white; border: 2px solid red; font-weight: 700; } I would like to achieve a similar effect, where a change in the font-size (specified in rem) changes the padding around the text and svg proportionally, aswell as the size of the svg. I have attached an image of the scalable button that I am trying to create. Does anyone have any ideas how I might create this?
8 Replies
Using
em
units is how you achieve proportional scaling relative to font size, but you already have that set so what seems to be the problem?I'm trying to add the svg icon and things aren't working . I don't know what, to use. Could I use flexbox and still achieve a scalable button? Should I place everything the h2 element and svg in a div? Also a bit lost, as to how I could achieve consistent padding on both the left side where the text is and the right side where the svg is. This is the code I have came up with. <div className={
btn btn--${props.buttonType} button--${props.size}
}>
<h2 className={btn__${props.buttonType}--text
}>Vote</h2>
<svg xmlns="http://www.w3.org/2000/svg" width="400px" height="400px" viewBox="0 0 24 24" fill="none" className="svg">
<path d="M20.498 15.5H3.5V20.5H20.498V15.5ZM21.9445 14.4719L21.9661 14.5336L21.9892 14.6345L21.9981 14.7331V21.25C21.9981 21.6297 21.7159 21.9435 21.3499 21.9932L21.2481 22H2.75C2.3703 22 2.05651 21.7178 2.00685 21.3518L2 21.25V14.7506L2.00184 14.6977L2.01271 14.6122C2.02285 14.5584 2.03841 14.5072 2.05894 14.4587L4.81824 8.44003C4.92517 8.2068 5.14245 8.04682 5.39153 8.01047L5.5 8.0026L8.03982 8.00183L7.25089 9.37206L7.18282 9.50183L5.981 9.502L3.918 13.9998H20.07L18.0428 9.65383L18.9052 8.15653C18.9718 8.20739 19.0301 8.26957 19.0771 8.3411L19.1297 8.43553L21.9445 14.4719ZM13.3652 2.05565L13.4566 2.10062L18.6447 5.10375C18.9729 5.29371 19.1033 5.69521 18.9636 6.03728L18.9187 6.1289L16.112 11.001L17.25 11.0016C17.6642 11.0016 18 11.3374 18 11.7516C18 12.1313 17.7178 12.4451 17.3518 12.4948L17.25 12.5016L15.248 12.501L15.2471 12.504H11.1691L11.166 12.501L6.75 12.5016C6.33579 12.5016 6 12.1658 6 11.7516C6 11.3719 6.28215 11.0581 6.64823 11.0085L6.75 11.0016L8.573 11.001L8.39145 10.8963C8.06327 10.7063 7.93285 10.3048 8.0726 9.96272L8.11747 9.8711L12.4341 2.37536C12.6235 2.04633 13.024 1.91557 13.3652 2.05565ZM13.3559 3.77529L9.78781 9.97119L11.566 11.001H14.383L17.248 6.02818L13.3559 3.77529Z" fill="#212121"/>
</svg>
</div>Remove the width and height attribute and set it in CSS using
em
units
Or just set the width and height attributes to em units right inside the SVG so it's inlinedOk. So I think I have got there. I have had to use a css variable on the parent btn. This than changes the font size of the button text and than the width and height of the svg (based on font-size). To change the size of the button you need to change the font-size and the --font-size in the parent .btn. This is my css. Does this look good? .btn{
display: inline-flex;
align-items:center;
font-size: 2rem;
--font-size: 2rem;
padding: 0.5em 1em;
gap: 0.5em;
font-family: "DM Serif Text", "Roboto", "Open Sans", sans-serif;
letter-spacing: 1.5px;
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
.btn__text {
font-size: var(--font-size);
}
.svg{
width: calc(var(--font-size) * 1.4);
height: calc(var(--font-size) * 1.4);
fill: red;
}
.btn--primary{
background-color: white;
border: 2px solid red;
color: red;
}
Almost but a lot of it is pretty complicated...I don't even think you need the variable. I'm on mobile so it's tough to write the CSS for you but just set the font size to be 2rem on the .btn, then font-size: 1em on the .btn__text, and then 1.4em for the svg width and height. It uses the closest declared ancestors font size as the basis for em
You can use em further down, doesn't just have to be element having the font size declared
Also, even if you did use the variable, for .btn you should have done:
Again though, don't think it's necessary
DO NOT DO THIS: set a *sensible" width and height in the svg, then set an appropriate width and height in css using em or ch or ex or lh or whatever unit you see fit
removing the width and height of an svg makes it so the width is 100% and the height is proportional
that can lead to a page that is one giant svg, until the page loads completely, with all the css
Ok. So I have made some changes. Removed the font--size attribute and specified svg just with the width. It's creating a resizable button. Does this look good?
don't use px for the letter spacing
by the way, i've hand-optimized this, and used an automated tool to optimize some things too.
this is the path i got from it, which is about 1000 characters smaller
and if i round to 2 decimal places, i got this:
which is about 1300 characters smaller
https://yqnn.github.io/svg-path-editor/ i've used this
it won't look perfectly the same, but it is still a nice chunk in savings