Smart contracts have to be written in a language which can be compiled into the right type of bytecode. So in theory any language will do but in reality Solidity is almost the only option - there are a few other small niche languages (Serpent, LLL) but with not much usage.
On top of the smart contract is some client which interacts with the blockchain - typically Geth or Parity. This is usually not written by hand but a ready client is used. Or you can use a ready service provider's node, such as Infura.
On top of the client (or client connection) you can build whatever you want with whatever you want. If it's a web interface you want some HTML code in some fashion. Or it can be some other type of interface such as a desktop app. The main point is that the user interface side can be written with anything and after the node connection (Client) part starts the niche blockchain code.