Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] Arquitetando CSS

Recommended Posts

Existe umgrande problema com o CSS, que é sua falta de ?estrutura?. Quando você tem umprojeto de 20 páginas, tudo bem ? jogue tudo em um arquivo. Quando você temcentenas de paginas, em dezenas de agências de design diferentes, as coisascomeçam a ficar bastante bagunçadas.

E euodeio bagunça.

Umcliente meu está nessa situação. Por três anos, eles tiverem seis designersdiferentes, cada um com estilos visuais diferentes ? mas, o que é maisimportante para mim ? cada um com diferentes requisitos e implementações CSS.

O impactodisso tem me incomodado desde que eu comecei, mas eu sempre tive mais problemas?arquiteturais? para lidar. No entanto, eu decidi que era o suficiente quandopercebi que nossa carga total paga de CSS era de 1 MB, e nosso maior arquivo CSSpossuía mais de 5 mil linhas.

Arquitetando o CSS

Existemalgumas coisas que quero do meu CSS:

  • Ultimamente, sou em maior parte um desenvolvedor C#, então eu gosto da coisa orientada a objeto ? eu entendo, é organizado e reutilizável.
  • A parte de ?cascata? do CSS é maravilhosa, mas é uma espada de dois gumes. Quando algum designer insere uma stylesheet com uma tag como ?.main h2?, ela irá inevitavelmente afetar porções do site que não estavam envolvidas.
  • Os problemas com o CSS somente se manifestam quando você de fato os visualiza ? em outras palavras, eles são erros de execução. E quando você tem centenas de páginas no site, geralmente é o usuário que reporta um problema de estilo, não nossos ?testadores?.

Perto, mas não perto o suficiente

Infelizmente,não posso afirmar que sou capaz de consertar nenhum desses problemas. Admiro aambição de projetos como o.less (www.dotlesscss.org/), mas há algo neles que nãoparece certo para mim. Acho que é porque não existe suporte para mainstream(suporte para mainstream é muito importante para mim, pois tenho um streamconstante de novos desenvolvedores entrando ? padrões são meus amigos).

Eu tambémli muitas opiniões de pessoas sobre CSS ? como precisamos nos afastar dasemântica, como precisamos nos aproximar da semântica etc... mas, mais uma vez,preciso de algo que tenha amplo suporte da comunidade na internet, e que meusnovos desenvolvedores serão capazes de acompanhar.

Um compromisso brilhante

Portanto,no ínterim, enquanto eu procuro pela solução perfeita, encontrei uma soluçãomuito boa. Ela consiste em um único user control. Você pode chamá-lo de WonderControl,mas eu simplesmente o chamo de CssContainer.ascx:

ASCX

<asp:PlaceHolder runat="server" ID="PHStyle" />

Code-behind

public partial class CssContainer : BaseUserControl

{

 

[

PersistenceMode(PersistenceMode.InnerProperty),

TemplateContainer(typeof(CssContainer)),

TemplateInstance(TemplateInstance.Single),

]

public ITemplate Style { get; set; }

 

/// <summary>

/// Init

/// </summary>

/// <param name="e"></param>

protected override void OnInit(EventArgs e)

{

// Instantiate any CSS in our template

this.EnableViewState = false;

base.OnInit(e);

if (Style != null) Style.InstantiateIn(PHStyle);

}

 

/// <summary>

/// Pre render

/// </summary>

/// <param name="e"></param>

protected override void OnPreRender(EventArgs e)

{

base.OnPreRender(e);

 

// If, for some reason, the control is called twice, we ignore

if (!HasRegisteredOnThisRequest())

{

this.Visible = true;

this.RegisterStyles();

}

else

{

this.Visible = false;

}

}

 

/// <summary>

/// This control is designed to render styles only once per request - duplicate styles are a waste of resources

/// </summary>

/// <returns></returns>

private bool HasRegisteredOnThisRequest()

{

 

// Has this control been rendered before?

Control parent = this.Parent;

while (true)

{

if (parent == null) break;

if (parent.GetType().IsSubclassOf(typeof(BaseUserControl)) || parent.GetType().IsSubclassOf(typeof(PageBase)))

{

break;

}

parent = parent.Parent;

}

if (parent == null)

{

// I'll throw an exception here, but really you could just render it anyway - it would just result in multiple renderings per page

throw new Exception("CssContainer may only be used on classes inheriting from BaseUserControl or PageBase");

}

 

// The count is kept in the PageBase so that we may retain it per-request, but share across all instances of this CssContainer control

if (!this.Page.GetType().IsSubclassOf(typeof(PageBase)))

{

// I'll throw an exception here, but really you could just render it anyway - it would just result in multiple renderings per page

throw new Exception("CssContainer may only be used on pages inheriting from PageBase");

}

 

// This control is probably specified multiple times on any one page. Here, we record that its' been done already or not

if (pageBase.CssContainerCount.ContainsKey(parent.GetType())) return true;

pageBase.CssContainerCount[parent.GetType()] = 1;

return false;

}

 

/// <summary>

/// Register the script contents, if any, to the page

/// </summary>

private void RegisterStyles()

{

// Pull template string OUT of the template we rendered in initially

var sb = new StringBuilder();

var tw = new StringWriter(sb);

var writer = new HtmlTextWriter(tw);

this.PHStyle.RenderControl(writer);

writer.Close();

tw.Close();

var css = sb.ToString();

if (string.IsNullOrWhiteSpace(css)) return;

 

// User controls can be in multiple folder paths, so we must normalize any URLs

css = css.Replace("~/", WebHelpers.GetFullUrlForPage(""));

 

// Compress CSS etc

css = Yahoo.Yui.Compressor.CssCompressor.Compress(css);

 

// Render to page

this.PHStyle.Visible = false;

this.Controls.Add(new LiteralControl("<style type="text/css">" + css + "</style>"));

}

}

Okay, umpouco espalhafatoso, mas realmente, muito simples. Eu tentei comentar o códigointuitivamente para que você consiga segui-lo, mas a ideia geral é:

  1. O usuário do controle especifica um CSS regular em um template (chamado Style)
  2. Renderizamos esse conteúdo dentro do placeholder PHStyle, da mesma maneira que você faria com um template normal
  3. Então tiramos o CSS de volta do template, e renderizamos para a página entre regular <style/> tags

Então o uso final é algo assim:

<wc:Css runat="server">

<Style>

.column-con {

overflow: hidden;

}

.column-con .column {

background-color: #fff;

}

</Style>

</wc:Css>

Aintenção é que você solte esse CSS diretamente dentro da página /usercontrol queo está usando.

Por que isso é ruim...

Sim,entendo que os problemas com isso são:

  1. É inline, o que significa que as requisições de página são maiores
  2. Não pode ser cached no browser
  3. Somente pode ser reutilizado se estiver sob a página ou usercontrol que está o utilizando

Mas aresposta para todos eles é simples: se a dor de quebrar essas regras, para esseconjunto de estilos, for muito grande, então apenas coloque-as de volta em sua stylesheet regular externa do CSS.

Essecontrole não tem o intuito de substituirsuas sheets externas, mas sim de complementá-las.

Então por que isso é bom...

Existesomente uma razão: é organizado. Onde temos um user control obscuro ou umapágina cujos estilos se afastam significantemente dos nossos estilos usuais,essa é uma maneira brilhante de isolar os estilos sem desordenar a style sheet principal.

E comoela é renderizada em código (em oposição a usar diretamente <style/>tags), sei que tenho bastante controle sobre o que desejarei fazer com isso nofuturo. Por exemplo, eu poderia:

  1. Falsificar uma referência a um ?arquivo? externo usando um handler, permitindo assim que o pedido resultante fique como cache no browser
  2. Minimizar o CSS (na verdade, já estou fazendo isso no exemplo acima)
  3. Executar substituições como nomes variáveis ? como eles fazem em  www.dotlesscss.org/
  4. Posso facilmente encontrar os estilos que se aplicam ao meu HTML, apenas visualizando o topo do UserControl ? não preciso mais executar ?Search Entire Project? para descobrir a fonte do CSS (atualização: Resharper 6 tem uma boa implementação do ?Go To Definition? para CSS)
  5. etc etc etc

Mas atéque eu saiba como lidar com minhas sheets, essa solução me permite contê-las egerenciá-las muito melhor do que os arquivos CSS do ?lado cliente? e astags incorporadas permitem.

Mas e as style sheets externas reutilizáveis?

Anteriormente,onde isolamos o CSS, também criamos arquivos CSS separados, e então oscolocamos dentro do pedido ?on-demand?. Tecnicamente, isso funcionou tãobem quanto minha solução acima ? na verdade, foi melhor quando o arquivoresultante estivesse em cache no browser do cliente e portanto melhoraria avelocidade da visita de modo geral.

Mas issopode resultar em dezenas (ou muito mais) de arquivos CSS se acumulando em seuprojeto, confundindo seus desenvolvedores, atrasando o tempo de carregamento doseu projeto etc. Além disso, como disse acima, sei que depois, quando euestiver menos ocupado, poderei criar referências ?externas? usando handlers ASHX.

Mas estilos incorporados são terríveis!!

Emteoria, sim ? mas, na prática, definitivamente não. Uma das piores coisas que umdesenvolvedor pode fazer é ficar preso na ?melhor prática?. Desde que vocêcompreenda as razões por trás das regras, você será capaz de quebrá-las quandoachar que as razões não se aplicam ao seu projeto atual.

Alémdisso, faça um ?view source? em qualquer uma dessas home pages ? você verámuitos estilos incorporados:

Viu?Estou em boa companhia.

Conclusão

Este nãoé o trabalho técnico mais brilhante que já fiz, mas tenho que dizer que foi umdos mais excitantes. Eu adoro ser capaz de adicionar estilosdespreocupadamente, exatamente como gosto de pouco cuidado com a estrutura ?conteúdo no conhecimento que o futuro Ben será capaz de organizar tudofacilmente um dia.

Eufortemente encorajo outros desenvolvedores a considerar esse tipo de estruturapara qualquer projeto médio-grande em que eles estiverem trabalhando.

?

Texto original disponível em http://blog.blackballsoftware.com/2011/08/26/architecting-cascading-style-sheets-css/

 

http://imasters.com.br/artigo/22288/css/arquitetando-css

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.