diff --git a/float_labels.info.yml b/float_labels.info.yml
index ed30cb7..9c3a1c4 100644
--- a/float_labels.info.yml
+++ b/float_labels.info.yml
@@ -1,6 +1,6 @@
 name: Float Labels
 type: module
 description: 'Applies configurable, JS-enhanced floating CSS labels to Drupal forms.'
-core_version_requirement: ^10 || ^11
+core_version_requirement: ^10.1 || ^11 || ^12
 package: Forms
 configure: float_labels.admin_settings
diff --git a/float_labels.module b/float_labels.module
index dedc3b7..16f7227 100644
--- a/float_labels.module
+++ b/float_labels.module
@@ -1,23 +1,16 @@
 <?php
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\float_labels\Hook\FloatLabelsHooks;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 /**
  * Implements hook_element_info_alter().
  */
-function float_labels_element_info_alter(array &$types) {
-  $allowed_types = ['form', 'textarea', 'textfield', 'tel', 'email', 'url',
-    'password', 'password_confirm'];
-
-  if (\Drupal::config('float_labels.settings')->get('select_field_default_value')) {
-    $allowed_types[] = 'select';
-  }
-
-  foreach (array_keys($types) as $type) {
-    if (in_array($type, $allowed_types)) {
-      $types[$type]['#process'][] = 'float_labels_process_element';
-    }
-  }
+#[LegacyHook]
+function float_labels_element_info_alter(array &$types)
+{
+    \Drupal::service(FloatLabelsHooks::class)->elementInfoAlter($types);
 }
 
 /**
diff --git a/float_labels.services.yml b/float_labels.services.yml
new file mode 100644
index 0000000..84c3b97
--- /dev/null
+++ b/float_labels.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\float_labels\Hook\FloatLabelsHooks:
+    class: Drupal\float_labels\Hook\FloatLabelsHooks
+    autowire: true
diff --git a/src/Hook/FloatLabelsHooks.php b/src/Hook/FloatLabelsHooks.php
new file mode 100644
index 0000000..3348a41
--- /dev/null
+++ b/src/Hook/FloatLabelsHooks.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\float_labels\Hook;
+
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Hook\Attribute\Hook;
+/**
+ * Hook implementations for float_labels.
+ */
+class FloatLabelsHooks
+{
+    /**
+     * Implements hook_element_info_alter().
+     */
+    #[Hook('element_info_alter')]
+    public static function elementInfoAlter(array &$types)
+    {
+        $allowed_types = [
+            'form',
+            'textarea',
+            'textfield',
+            'tel',
+            'email',
+            'url',
+            'password',
+            'password_confirm',
+        ];
+        if (\Drupal::config('float_labels.settings')->get('select_field_default_value')) {
+            $allowed_types[] = 'select';
+        }
+        foreach (array_keys($types) as $type) {
+            if (in_array($type, $allowed_types)) {
+                $types[$type]['#process'][] = 'float_labels_process_element';
+            }
+        }
+    }
+}
