In many libraries delay cells are available. So no need to use discrete buffers or inverters. You can directly take instance of this cell as per your delay requirment.
Except from buffers and delay cells, you can use whatever mix of gates you want to create
delays... The only contstraint is that you have to use them in a way that they work in a monotonic way, i.e. during the evaluation of the delay every gate should only go once from 0->1 or from 1->0.