diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 82aabd04d83..333e0b0be87 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -47,6 +47,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1881,6 +1882,41 @@ WebIDL::ExceptionOr HTMLInputElement::set_size(WebIDL::UnsignedLong value)
return set_attribute(HTML::AttributeNames::size, String::number(value));
}
+// https://html.spec.whatwg.org/multipage/input.html#dom-input-width
+WebIDL::UnsignedLong HTMLInputElement::width() const
+{
+ const_cast(document()).update_layout();
+
+ // When the input element's type attribute is not in the Image Button state, then no image is available.
+ if (type_state() != TypeAttributeState::ImageButton)
+ return 0;
+
+ // Return the rendered width of the image, in CSS pixels, if the image is being rendered.
+ if (auto* paintable_box = this->paintable_box())
+ return paintable_box->content_width().to_int();
+
+ // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name.
+ if (auto width_string = get_attribute(HTML::AttributeNames::width); width_string.has_value()) {
+ if (auto width = parse_non_negative_integer(*width_string); width.has_value() && *width <= 2147483647)
+ return *width;
+ }
+
+ // ...or else the natural width and height of the image, in CSS pixels, if an image is available but not being rendered
+ if (auto bitmap = current_image_bitmap())
+ return bitmap->width();
+
+ // ...or else 0, if the image is not available or does not have intrinsic dimensions.
+ return 0;
+}
+
+WebIDL::ExceptionOr HTMLInputElement::set_width(WebIDL::UnsignedLong value)
+{
+ if (value > 2147483647)
+ value = 0;
+
+ return set_attribute(HTML::AttributeNames::width, String::number(value));
+}
+
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-number
Optional HTMLInputElement::convert_string_to_number(StringView input) const
{
diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.h b/Libraries/LibWeb/HTML/HTMLInputElement.h
index 964bc121f5c..1a6dc787bdc 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -128,6 +128,9 @@ public:
WebIDL::UnsignedLong size() const;
WebIDL::ExceptionOr set_size(WebIDL::UnsignedLong value);
+ WebIDL::UnsignedLong width() const;
+ WebIDL::ExceptionOr set_width(WebIDL::UnsignedLong value);
+
struct SelectedCoordinate {
int x { 0 };
int y { 0 };
diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.idl b/Libraries/LibWeb/HTML/HTMLInputElement.idl
index 1ed87bf4d2e..eba5df54d9d 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.idl
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.idl
@@ -43,7 +43,7 @@ interface HTMLInputElement : HTMLElement {
[CEReactions, LegacyNullToEmptyString] attribute DOMString value;
attribute object? valueAsDate;
attribute unrestricted double valueAsNumber;
- [FIXME, CEReactions] attribute unsigned long width;
+ [CEReactions] attribute unsigned long width;
undefined stepUp(optional long n = 1);
undefined stepDown(optional long n = 1);
diff --git a/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt b/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt
index 2f8169498cb..d1c0fac3f76 100644
--- a/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt
+++ b/Tests/LibWeb/Text/expected/HTML/unsigned-long-reflection.txt
@@ -37,6 +37,26 @@ input.getAttribute("size") after input.setAttribute("size", "4294967295"): 42949
input.size after input.setAttribute("size", "4294967295"): 20
input.getAttribute("size") after input.size = 4294967295: 20
input.size after input.size = 4294967295: 20
+input.getAttribute("width") after input.setAttribute("width", "0"): 0
+input.width after input.setAttribute("width", "0"): 0
+input.getAttribute("width") after input.width = 0: 0
+input.width after input.width = 0: 0
+input.getAttribute("width") after input.setAttribute("width", "1"): 1
+input.width after input.setAttribute("width", "1"): 1
+input.getAttribute("width") after input.width = 1: 1
+input.width after input.width = 1: 0
+input.getAttribute("width") after input.setAttribute("width", "2147483647"): 2147483647
+input.width after input.setAttribute("width", "2147483647"): 2147483647
+input.getAttribute("width") after input.width = 2147483647: 2147483647
+input.width after input.width = 2147483647: 0
+input.getAttribute("width") after input.setAttribute("width", "2147483648"): 2147483648
+input.width after input.setAttribute("width", "2147483648"): 0
+input.getAttribute("width") after input.width = 2147483648: 0
+input.width after input.width = 2147483648: 0
+input.getAttribute("width") after input.setAttribute("width", "4294967295"): 4294967295
+input.width after input.setAttribute("width", "4294967295"): 0
+input.getAttribute("width") after input.width = 4294967295: 0
+input.width after input.width = 4294967295: 0
marquee.getAttribute("scrollamount") after marquee.setAttribute("scrollAmount", "0"): 0
marquee.scrollAmount after marquee.setAttribute("scrollamount", "0"): 0
marquee.getAttribute("scrollamount") after marquee.scrollAmount = 0: 0
diff --git a/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html b/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html
index 00ff3915bb0..9b8177a6d21 100644
--- a/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html
+++ b/Tests/LibWeb/Text/input/HTML/unsigned-long-reflection.html
@@ -2,10 +2,19 @@