The window function first_value() allows for a rather short and elegant solution:
SELECT first_value(a) OVER (ORDER BY a IS NULL, ts) AS a
     , first_value(b) OVER (ORDER BY b IS NULL, ts) AS b
     , first_value(c) OVER (ORDER BY c IS NULL, ts) AS c
FROM   t
LIMIT  1;
a IS NULL evaluates to TRUE or FALSE. FALSE sorts before TRUE. This way, non-null values come first. Order by ts (timestamp column like you commented) next and you've got it in a single SELECT.
This would be simpler if Postgres supported IGNORE NULLS. The manual:
The SQL standard defines a RESPECT NULLS or IGNORE NULLS option for
lead, lag, first_value, last_value, and nth_value. This is not
implemented in PostgreSQL: the behavior is always the same as the
standard's default, namely RESPECT NULLS.
One of the few omissions with regard to standard SQL in this area.
We also cannot use a FILTER clause. See:
The manual:
Only window functions that are aggregates accept a FILTER clause.
db<>fiddle here
Old sqlfiddle