diff --git a/core/includes/form.inc b/core/includes/form.inc
index a12fb34d0212e4acf8e42950dad629cc494a9d6e..aecf0daa3c3a4fcc592cc03672ac886cc73e6008 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -3792,13 +3792,27 @@ function theme_password($variables) {
  * Expand weight elements into selects.
  */
 function form_process_weight($element) {
-  for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
-    $weights[$n] = $n;
-  }
-  $element['#options'] = $weights;
-  $element['#type'] = 'select';
   $element['#is_weight'] = TRUE;
-  $element += element_info('select');
+
+  // If the number of options is small enough, use a select field.
+  $max_elements = variable_get('drupal_weight_select_max', DRUPAL_WEIGHT_SELECT_MAX);
+  if ($element['#delta'] <= $max_elements) {
+    $element['#type'] = 'select';
+    for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
+      $weights[$n] = $n;
+    }
+    $element['#options'] = $weights;
+    $element += element_info('select');
+  }
+  // Otherwise, use a text field.
+  else {
+    $element['#type'] = 'textfield';
+    // Use a field big enough to fit most weights.
+    $element['#size'] = 10;
+    $element['#element_validate'] = array('element_validate_integer');
+    $element += element_info('textfield');
+  }
+
   return $element;
 }
 
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 77d6ebfa46ee788c9ff66559c6dadf8b9d201baa..32b12833c2e0df783b55ffb9f2722f96e294d08d 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -45,6 +45,13 @@
  */
 const DRUPAL_REQUIRED = 2;
 
+/**
+ * Maximum number of values in a weight select element.
+ *
+ * If the number of values is over the maximum, a text field is used instead.
+ */
+const DRUPAL_WEIGHT_SELECT_MAX = 100;
+
 /**
  * Return only visible regions.
  *