I'm working on my unit conversion solo project from the Scrimba Front-End developer course, and I'm struggling hard to make my text input squarish yet responsive.
I managed to make it somewhat like the Figma design, but the issue is that if the number exceeds the width it gets hidden behind the input dimensions. So my goal is to create a squarish input field that extends depending on the text width.
Does anyone have an idea on how to do it? I tried working with AI and it didn't help this time, so I'd really appreciate an advice from an experienced fellow coder. Thanks!
Here is my code: https://github.com/Loud-Environment/unit-converter. I'm struggling on the /* Styling the header */ part witch the input rules.
Pasting the code excerpt below:
with input

without input

/* Styling the header */
body {
background-color: var(--background--);
color: var(--main-text--);
font-family: "Inter", sans-serif;
}
enter image description here header {
background-color: var(--accent-background--);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2.5em;
}
h1 {
font-size: calc(1.5rem + 1vh);
margin: 1em 1em 0;
}
input {
background-color: var(--accent-background--);
border: 2px solid var(--border-color--);
border-radius: 5px;
font-size: calc(3rem + 1vh);
font-weight: bold;
text-align: center;
flex: 1 auto auto;
width: 25vw;
text-wrap: wrap;
max-width: max-content;
display: block;
}
button {
background-color: #ffffff;
color: #3d3d3d;
font-size: calc(1rem + 1vh);
margin-bottom: 2em;
padding: 0.4em 1.5em;
border: 1px solid #ffffff;
border-radius: 5px;
}
<header>
<h1>Metric/Imperial Unit Conversion</h1>
<input type="text" />
<button>Convert</button>
</header>
You would need JavaScript. Here I use a hidden mirror to calculate the width precisely
I added CSS to grow smoothly
const input = document.getElementById('autoGrowInput');
const mirror = document.createElement('span');
mirror.style.position = 'absolute';
mirror.style.visibility = 'hidden';
mirror.style.whiteSpace = 'pre';
mirror.style.fontSize = getComputedStyle(input).fontSize;
mirror.style.fontFamily = getComputedStyle(input).fontFamily;
document.body.appendChild(mirror);
const updateWidth = () => {
const text = input.value || input.placeholder || '';
mirror.textContent = text;
const newWidth = mirror.offsetWidth + 30; // padding
input.style.width = newWidth + 'px';
};
input.addEventListener('input', updateWidth);
updateWidth();
/* Styling the header */
body {
background-color: var(--background--);
color: var(--main-text--);
font-family: "Inter", sans-serif;
}
header {
background-color: var(--accent-background--);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2.5em;
}
h1 {
font-size: calc(1.5rem + 1vh);
margin: 1em 1em 0;
}
input {
background-color: var(--accent-background--);
border: 2px solid var(--border-color--);
border-radius: 5px;
font-size: calc(3rem + 1vh);
font-weight: bold;
text-align: center;
flex: 1 auto auto;
width: 25vw;
text-wrap: wrap;
max-width: max-content;
display: block;
transition: width .2s ease;
/* smooth growth */
}
button {
background-color: #ffffff;
color: #3d3d3d;
font-size: calc(1rem + 1vh);
margin-bottom: 2em;
padding: 0.4em 1.5em;
border: 1px solid #ffffff;
border-radius: 5px;
}
<header>
<h1>Metric/Imperial Unit Conversion</h1>
<input type="text" id="autoGrowInput" />
<button>Convert</button>
</header>
Here is one that just counts characters
const input = document.getElementById('autoGrowInput');
// how many characters before we start growing
const maxCharsNoGrow = 6;
// remember the starting width in pixels
const baseWidth = input.offsetWidth;
const fontSize = parseFloat(getComputedStyle(input).fontSize);
// tune this factor if it grows too quickly or too slowly
const charWidthFactor = 0.6; // fraction of font-size per extra character
const updateWidth = () => {
const len = input.value.length;
if (len <= maxCharsNoGrow) {
input.style.width = baseWidth + 'px';
return;
}
const extraChars = len - maxCharsNoGrow;
const extraPx = extraChars * fontSize * charWidthFactor;
input.style.width = baseWidth + extraPx + 'px';
};
input.addEventListener('input', updateWidth);
updateWidth();
/* Styling the header */
body {
background-color: var(--background--);
color: var(--main-text--);
font-family: "Inter", sans-serif;
}
header {
background-color: var(--accent-background--);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2.5em;
}
h1 {
font-size: calc(1.5rem + 1vh);
margin: 1em 1em 0;
}
input {
background-color: var(--accent-background--);
border: 2px solid var(--border-color--);
border-radius: 5px;
font-size: calc(3rem + 1vh);
font-weight: bold;
text-align: center;
flex: 1 auto auto;
width: 25vw;
text-wrap: wrap;
max-width: max-content;
display: block;
transition: width .2s ease; /* smooth growth */
}
button {
background-color: #ffffff;
color: #3d3d3d;
font-size: calc(1rem + 1vh);
margin-bottom: 2em;
padding: 0.4em 1.5em;
border: 1px solid #ffffff;
border-radius: 5px;
}
<header>
<h1>Metric/Imperial Unit Conversion</h1>
<input type="text" id="autoGrowInput" />
<button>Convert</button>
</header>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With