As background, and to answer my own question (after some research), the <form>
tag in an Options screen is usually generated with code similar to this:
<form action='options.php' method='post'>
<?php
settings_fields( 'pluginPage' ); // initializes all of the settings fields
do_settings_sections( 'pluginPage' ); // does the settings section; into a table
submit_button(); // creats the submit button
?>
</form>
The do_settings_section()
function is part of the Options API, and is responsible for creating the option settings fields defined in add_settings_fields statements. (See https://developer.wordpress.org/reference/functions/do_settings_sections/ ).
The do_settings_section()
function eventually calls do_settings_fields()
which outputs (renders) the actual <input>
statements via the callback specified by add_settings_field()
. (See https://developer.wordpress.org/reference/functions/do_settings_fields/ ).
If we look at the code for do_settings_field
, we will find statements that output each settings field (into a table – sigh):
echo "<tr{$class}>";
if ( ! empty( $field['args']['label_for'] ) ) {
echo '<th scope="row"><label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label></th>';
} else {
echo '<th scope="row">' . $field['title'] . '</th>';
}
echo '<td>';
call_user_func($field['callback'], $field['args']);
echo '</td>';
echo '</tr>';
And we can see here the <th>
code for the field $title
(defined in the add_settings_field
definition of the settings field).
So, the only way to output settings fields without a table, in the format you want, is to bypass the do_settings_section()
in the <form>
with your own code, such as using your own my_render_fields()
function in the settings form:
<form action='options.php' method='post'>
<?php
settings_fields( 'pluginPage' ); // initializes all of the settings fields
my_render_fields(); // render fields without do_settings so no table codes
submit_button(); // creates the submit button
?>
</form>
Note that settings_field()
will also include the ‘nonce’ in the form, which is needed on Settings pages. (Not having a nonce can cause other errors on settings screens.)
Hope this helps others. Digging into the source code of WP functions sometimes gives you insights into problems. (I was hoping for a filter that would bypass the rendering of the field, but no such luck. But creating your own field rendering function is not hard.)