The issue is that an input
is not like a div
element and they won't behave the same. An input element will by default have styling set by the browser and you will notice that it also have a default width which is creating the issue.
If you refer to the specification or to this previous answer you will have the following formula:
'left' + 'margin-left' + 'width' + 'margin-right' + 'right' = width of containing block
Also a list of rules and in your case the width is never auto.
For your div you will fall into this rule:
- 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
Logically the width will be resolved after setting left and right and you will get the needed result.
For the input you will consider this:
If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values, unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and solve for 'margin-right' ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto', solve the equation for that value. If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that value.
A bit complex but in all the cases the width of the input will never change. Here is some basic example:
.box {
width:300px;
border:2px solid;
height:250px;
position:relative;
}
.box > input {
border:0;
background:green;
position:absolute;
}
.box > input:nth-child(1) {
left:0;
right:0;
}
.box > input:nth-child(2) {
top:50px;
left:100%;
right:0;
}
.box > input:nth-child(3) {
top:100px;
left:100%;
right:100%;
}
.box > input:nth-child(4) {
top:150px;
left:50px;
right:50px;
}
.box > input:nth-child(5) {
top:200px;
left:80px;
right:100%;
}
<div class="box">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
</div>
As you can clearly see, all the width are the same whataver the values of left/right you use and the left is deciding the position.
Your only solution is to override the width on the input element. So instead of left/right you can set left and width with width equal to 100% - L - R
where L
is the left value and R
the value you would have used for right.
.box {
width: 300px;
border: 2px solid;
height: 400px;
position: relative;
}
.box > input {
border: 0;
background: green;
position:absolute;
}
.box :nth-child(1) {
left: 0;
width: 100%;
}
.box :nth-child(2) {
top: 50px;
left: 80%;
width: calc(100% - 80%);
}
.box :nth-child(3) {
top: 100px;
left: 100%;
width: calc(100% - 100% + 50px);
}
.box :nth-child(4) {
top: 150px;
left: 50px;
width: calc(100% - 50px - 50px);
}
.box :nth-child(5) {
top: 200px;
left: 80px;
width: calc(100% - 80px);
}
<div class="box">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
</div>
You can also wrap your element inside another div and make the input width:100%
then use left/right on that div:
.box {
width: 300px;
border: 2px solid;
height: 400px;
position: relative;
}
.box div {
position:absolute;
}
.box input {
border: 0;
background: green;
width: 100%;
}
.box div:nth-child(1) {
left: 0;
right: 0;
}
.box div:nth-child(2) {
top: 50px;
left: 80%;
right: 0;
}
.box div:nth-child(3) {
top: 100px;
left: 100%;
right: -50px;
}
.box div:nth-child(4) {
top: 150px;
left: 50px;
right: 50px;
}
.box div:nth-child(5) {
top: 200px;
left: 80px;
right: 0;
}
<div class="box">
<div><input type="text"></div>
<div><input type="text"></div>
<div><input type="text"></div>
<div><input type="text"></div>
<div><input type="text"></div>
</div>