Resposta curta
De acordo com a especificação atual, sim, os styleelementos devem sempre estar no head. Não há exceções (exceto um styleelemento dentro de um templateelemento , se você quiser contar isso).
Esse nem sempre foi o caso historicamente. Se você se preocupa com os detalhes das especificações e seu histórico, continue lendo.
Não importa o que a especificação diz, usando styleelementos no body faz mais ou menos trabalho em todos os principais navegadores. No entanto, é considerada uma má prática, tanto por violar especificações quanto por causar conseqüências indesejáveis, como pior desempenho de renderização ou um "flash de conteúdo não estilizado".
Histórico de especificações
styleelementos não existiam no HTML 2 . Eles foram introduzidos no HTML 3.0, onde foram incluídos na lista de elementos que poderiam ser incluídos no The Head Element , mas não incluídos na lista de elementos que poderiam estar presentes no The Body Element . Assim, no momento em que o elemento foi especificado pela primeira vez, ele só pôde ser incluído no head.
Este permaneceu o caso (embora expresso usando palavras diferentes) até o HTML 5, que introduziu o scopedatributo (desde que removido) para os styleelementos. Esse atributo, quando presente, tinha como objetivo permitir que um styleelemento fosse colocado dentro de um elemento no corpo para estilizar apenas os descendentes desse elemento. No entanto, esse recurso nunca chegou a nenhum navegador real (pelo menos não sem a necessidade de ser ativado por um sinalizador de desenvolvedor) e foi removido das especificações do W3C e do WhatWG "devido à falta de interesse do implementador" . Depois disso,style elementos foram permitidos apenas em contextos que permitem conteúdo de metadados, que é apenas o cabeçalho. Assim, voltamos às mesmas regras de antes do HTML 5.
No entanto, devido a um erro cometido pelas duas organizações de especificações, um índice não normativo de elementos incluídos como apêndice nas duas especificações não foi atualizado adequadamente para refletir a remoção de scoped, tornando-o inconsistente com a especificação normativa. Eu apontei isso para o WhatWG e para o W3C e, ao fazê-lo, involuntariamente desencadeou eventos que fizeram com que as duas especificações divergissem.
A solução da WhatWG para a inconsistência entre a especificação normativa e o índice não normativo foi aceitar meu patch corrigindo o índice não normativo.
O W3C, por outro lado, rejeitou meu patch equivalente em vez de atualizar a especificação normativa para permitir o uso de styleelementos no body, enquanto ressalta isso com uma nota de que ele pode causar problemas e deve ser feito "com cuidado". O raciocínio por trás dessa mudança foi alinhar as especificações com o comportamento do navegador da vida real.
Portanto, a partir de março de 2017, a resposta oficial a essa pergunta dependia de qual organização de padrões você escolheu ouvir. Se você listou as especificações WhatWG (geralmente mais respeitadas), um styleelemento não era permitido na body. Se você listou as especificações do W3C, isso foi permitido, mas não recomendado.
Esse estado de coisas tolo foi encerrado (talvez como muitas outras inconsistências) com o tratado de paz de abril de 2019 entre o W3C e o WhatWG , que concordou que as especificações do WhatWG se tornariam o único verdadeiro padrão HTML vivo, com o W3C apenas liberando instantâneos como numerados Especificações HTML em vez de desenvolver uma especificação concorrente em paralelo. Assim, a mudança de 2017 para o fork do W3C que permitiu styleelementos nobody não faz mais parte de nenhuma especificação atual; é apenas uma curiosidade da história.
Então, hoje, precisamos apenas olhar para a especificação WhatWG para determinar o que é oficialmente permitido. Tem o seguinte a dizer:
4.2.6 O styleelemento
Conteúdo de metadados .
Onde o conteúdo de metadados é esperado.
Em um <noscript>elemento que é filho de um <head>elemento.
CTRL-Fing através da especificação de página única revela que o único elemento cujo modelo de conteúdo inclui conteúdo de metadados é o headelemento.
O índice não normativo dos elementos que mencionei anteriormente, também confirma que os únicos pais permitidos para um styleelemento são a headou noscriptelemento.