Currently, the only way to add custom fields to the sortable attributes is to write a custom plugin which makes use of the
modifyEntrySortableAttributes hook, e.g.:
public function modifyEntrySortableAttributes(&$attributes)
$attributes['yourCustomFieldHandle'] = Craft::t('Label');
$attributes['anotherCustomField'] = Craft::t('Another label');
modifyEntrySortableAttributes method would go into your plugin's primary class.
Apart from custom fields, it's also possible to add other attributes in this manner, such as
authorId (to sort on author) or
typeId (to sort on entry type).
It's also possible to remove a sortable attribute:
There are corresponding hooks for adding sortable attributes to category, asset and user index tables, see the official docs for details.
One gotcha to note is that since the sortable attributes are source agnostic (i.e. they're the same across all sections), any custom field you add to the sortable attributes should ideally exist for all your entry types, as attempting to sort on a custom field that doesn't exist for the entries in the current index table will throw an error.
Moving into opinionated waters here, but to close: While the Customizable Element Indexes (CEI) is a great thing to have in core (and with a brilliant UI), I personally feel there's room for improvement; especially pertaining to sortable attributes. On that note, there are a few relevant feature requests:
I just published a new plugin which will add any (sortable) custom field or meta value in any given element index to the index' sortable attributes: https://github.com/mmikkel/CpSortableCustomColumns-Craft
The plugin is source aware, so it should avoid the issue with sorting on non-existing fields (as described above) in most cases. Like most Control Panel-specific plugins, it's basically one big hack – but it works until we can have better sorting abilities in core. Hopefully it's useful to someone!