How should I handle this CSS Inheritance conundrum? - javascript

I have a class of images called glyphs that appear through out my site. Once upon a time they were all called just called glyph. They used to only appear in one box. That box was a specific size and I used a javascript method to make sure the text always fit and the glyphs were always about the same height as the rest of the text. This was easy to do and the glyphs started off with a default due to my style sheet.
Now, I've decided to include multiple boxes per page with variable amounts of text. Each box gets sized independently. I've tried delaying the sizing routine, but this is highly reliant on a user's connection speed. If I don't run the sizing routine then things don't look right at all, so I'd at least like to pick a default starting size for everything. Of course, you can't size stuff with javascript until it has been loaded. Snake eats tail.
So basically, now that I have more than one box, each glyph gets a class glyph:1, glyph:2, etc. This number can go as large as the number of user submitted items on my site. How does CSS handle this? These items basically need two class names as far as I can see. But I'm pretty sure that's not allowed.
What I need: Set all images classes that begin with "glyph:" to 1em
This doesn't exist, right? glyph:*
Also, : is probably bad to use in a css class name, huh?

Don't use the : symbol. you can have more than one class for an element so do it like so
<div class="glyph glyph-1">Foo</div>
<div class="glyph glyph-2">Foo</div>
<div class="glyph glyph-3">Foo</div>
<div class="glyph glyph-4">Foo</div>

As others have said, you shouldn't use the colon symbol in class names. Hyphens and dashes are the only punctuation that is sensible to use.
It is possible to use colons in classes and escape them in your CSS code, but it gets really messy and is unnecessary.
Secondly (and this is where I'll go further than the other answers), if you're generating unique class names for your elements then you're probably doing something wrong.
The id attribute is there to give your elements a unique name; the class is intended to allow you to apply the same class (or classes) to multiple elements, thus allowing you to style all those elements the same. You probably know this already; I guess what I'm saying is that it sounds like you should be using id rather than class.
Next: You say you're pretty sure two class names is not allowed, but in fact it is allowed. It is perfectly permissible to have class="glyph bob" and your element will pick up styles from both class glyph and class bob. You can have as many classes as you like. I would still say, however, that if you want to give them unique names, it should be an ID.
You also ask for CSS syntax to set all the glyph* classes. Again, you're wrong: this syntax does exist, via the extended attr syntax:
[class^="glyph"] {
/*styles here for classes beginning with 'glyph'
}
You talk about delaying the sizing routine, and the problems that introduces. One solution to this could be to have the items hidden entirely until the browser has finished working out how they should look. You could even fade them into view or something to make it look like it was a deliberate effect.
But after all that, I'm left wondering why you're putting glyphs in images and sizing them independently? It all sounds a bit odd; your description in the question leaves me wondering what you're trying to achieve.
Have you considered using scalable graphics (SVG/VML) or a custom font for your glyphs, rather than images? If you used a custom font, you could simply specify the font size as normal, and let the browser work it all out.
Hope some of that was helpful.

CSS class names can't contain the : symbol. Everything after the : will be interpreted as a pseudo-class (like :hover) and will not be parsed properly.
As for your classes, why do they all have to be unique? Classes are made to select multiple elements at once, so you can just do this:
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
<div class="glyph">Foo</div>
And select them all with one selector:
.glyph {
color: red;
}

Related

Unsure of the technical term - HTML/CSS/Javascript table questions

I have an HTML/CSS/Javascript related question, but I'm unsure of exactly how to ask, as I've long since forgotten the technical terms for everything.
My ultimate goal is to construct (code) a webpage element that does the following:
-Has a number of clickable elements (graphical buttons, not HTML "buttons") that, when clicked, display a variable amount of text that provides interesting details about certain things. If possible, some way to have these buttons "highlight" would be desired (I know how to pull off a CSS trick where the image is swapped up/down or left/right by coordinates when clicked, but I'm unsure of how to get this to work with what I intend).
-Allows me to affix some kind of a label in front of each button. (My original plan was to throw everything into an HTML table, so I could have a column on one side of the buttons that I can type labels into).
-Allows me to have an image background appear when the detail box pops up.
-Is organized such that the buttons and their title plates are on one side of the detail box, and the detail box itself is on the other side.
Example:
I have a column on the far left that has names of fruits (Apple, Orange, Banana, Pear). In a column immediately next to these names is a series of buttons aligned with each fruit name (one button per fruit name, so "Apple" then {button} on one row, then "Orange" then {button} on the next row, etc.). Clicking on that button will display, on the far right, a detailed description of each fruit, with a background image (same image for all of these detail boxes) behind this detailing text. This background image, and any text, would be hidden until a button is clicked. I would prefer it that if the same button is clicked twice, the text is once again hidden.
I've no problem constructing images for all of this, but I'm lost on the code. Is it possible to code all of this as some sort of HTML Table, so I can keep it organized? Would it be possible to have the far left column (example) have a background image, then replaceable text on top of it (thus decreasing the number of graphics)?
I apologize if my question and phrasing isn't technically descriptive. I've long since gotten too used to simple HTML pages and never really learned CSS/Javascript. If my question doesn't make sense, I'd be more than happy to draw an image to better explain my goal.
Thanks in advance for any responses.
Well, there's no single "right" way to do what you're asking. There's dozens of ways to approach this problem. It comes down to: 1) How much time do you want to spend building the solutions, and 2) Would it be an issue if you added different technologies to your project (such as Bootstrap or jQuery)?
To look it at from a general viewpoint:
There's a rule of thumb I heard somewhere that I think helps in situations like this. Every single thing on your page is a rectangle. Everything. All you're really doing is naming, styling, and manipulating these rectangles.
Any element, id, or class that you create on your html page can be manipulated by your css or javascript. And if it doesn't exist on your html page, then you can create it with css or javascript and then manipulate it.
Anything can be made into a "button", not just items specifically called out as buttons. You can choose whichever rectangles you want to be your "buttons"; you would just have to target and style them as such.
(As a piece of advice, though, I would recommend sticking with html's <button> functionality. Standardized semantics is good for everyone all around, and you can change the look and feel of these buttons however you want by using css).
To be more specific:
The traditional way to handle the hiding or showing of information on the page is by using javascript and/or jQuery.
Give all common html elements to be manipulated a class name class="example-class", and give any unique elements to be manipulated an id name id="example-id".
Here's the jQuery page regarding .hide() and .show(). (If you have any specific issues with these methods, then Stack Overflow can help). You would target the classes or ids that you named in the html.
As for organizing your page, using and nesting <div> tags is usually the way to go. Bootstrap comes with special classes that can help with the necessary roles: class="row" to help with the horizontals, class="col-SIZE-NUM" to help with the verticals, and class="well" to help with organizing sections.
Bootstrap's main page has a pretty good overview on your options: Here.
All of the above can be done with vanilla css and vanilla javascript as well. It's up to you to decide if you want to (or are even able to) make things a little easier for yourself here.
Hope this helps!

Splitting HTML Text Content into Groups while Preserving HTML Layout

I'm currently wondering about the ability to apply dynamic formatting to content in an HTML page without changing the flow rules. At face value, this might seem simple, since you can select a subset of the DOM and mass-apply. However, this would not work if you wanted to apply that formatting to a only one part of the text for a particular object.
For example, formatting:
<div>Let's start my format here <span> and here </span> and <br> here too. <br> But not here.</div>
If you wanted to exclude <br> But not here. from your formatting there is no clear way to do it for the case of an arbitrary layout, even if you did so manually. One approach is to break the div into span sections, then format them differently. Unfortunately, wrapping arbitrary HTML in inline elements causes some unfortunate side-effects (e.g., any <br> tag in a span will be treated as if it doesn't exist). Using a block element wrapper, like introduces similar issues by adding breaks that didn't exist. I cannot seem to find a way to declare a DOM group that can just plain act as if it were plain text within the parent object.
So then, I'm trying to figure out a good general workaround to introduce display-level formatting while preserving any layout formatting. This kind of formatting could include text formatting (e.g., highlighting, emphasis) or dynamic effects (e.g., hide/reveal). I can think of a few hypothetical solutions, but I am not sure what (if any) actually are possible in practice:
An existing inline layout element like span that doesn't kill your line breaks and other formatting requests.
The ability to make a custom element such as #1 using CSS. Maybe the run-in or inherit display tags might be useful for this purpose? (https://developer.mozilla.org/en-US/docs/Web/CSS/display) Neither of them seem like they solve this issue, however.
A way to prevent a span from clobbering formatting markup inside of it.
A grouping element that acts as a pass-through for layout formatting (i.e., is treated like untagged text for layout purposes) but allows display formatting.
One would think this would be a straightforward thing to do. After all, it's not hard to imagine wanting to split a div into two different sections that are text-formatted slightly differently, while retaining their layout formatting. However, I can't seem to find the right tool for this job.
After looking at this quite a while, the best that I came up with was to use span wrappers for the text nodes only, accompanied by clobbering the default CSS formats for spans. This had its drawbacks, but thankfully people often leave the basic span class alone.
However, considering it further, I think the best solution is actually to make a new type of span using webcomponents.js and then to make that span type always inherit the parent formatting. Particularly if that span type has a very arbitrary name (e.g., <span-(some guid)/>), that should be sufficient to prevent any chance of accidental conflict. I have also found that by wrapping only the text nodes, there is no chance of losing line breaks or other formatting, since those elements can never exist in a text node.
I am not necessarily saying this is the best answer, but it is the best one I've seen so far.

How to manually manage text wrapping in HTML

When working with designers, they often are very picky about word wrap in the completed HTML page. Assuming that I'm working on a fixed layout (not-responsive), and the designer does not like the way text is wrapping, I can:
Adjust padding-right
Add manual <br> to break a line
Add manual to avoid a break (typically for orphan control)
(In my case, I'm designing for a specific mobile device, so I know the screen size, and can control the fonts. Also, making the designers happy is non-negotiable.)
The issue that I keep running into is that the text or layout will be updated later, and relics of this specific word wrap concern, which no longer apply, introduce issues we then need to fix.
So I'm wondering if anyone can suggest a strategy that:
Allows completely arbitrary control of word wrap in individual
cases; but,
Doesn't make everything so hard to maintain going forward
I'm open to procedural, algorithmic (javascript), or CSS-oriented suggestions.
Here is the strategy I chose. Time will tell how maintainable it is.
Do not edit the text content
Fix wrapping by adding CSS classes that change the way the text flows, but do not use attributes like width or padding that are already being used to control layout
Specifically:
.tighten {
letter-spacing: -0.011em;
}
.loosen {
letter-spacing: 0.011em;
}
.hyphenate {
-webkit-hyphens: auto;
-webkit-hyphenate-limit-after: 4;
-webkit-hyphenate-limit-before: 4;
}
It turns out that these imperceptible changes in spacing can make a huge difference in wrap. I actually have several variations of these classes, so I can try progressively more or less space to fix wrapping.
In severe cases, I use the hyphenate class (I'm only targeting iOS in this case).
In a future revision, when we change the text in a div, we can just remove the tighten, loosen, or hyphenate class from that div, and see if there are any wrap issues we need to correct. If there are, we go through the original trial-and-error of seeing which class gives the best look.
Use <pre> tag so you can insert preformated text.

Jquery/Java Script: Customise an Image/Avatar by chainging options (e.g. Shape, Colour)

Lots of websites let you customize an image by changing options.
For example, this Barbie website lets you create your own Barbie doll. You can click on various hairstyles and clothes and the main image updates while you click.
Other clothes websites do similar things.
Are there any tutorials that show you how to do this with Java Script or Jquery?
Ideally, I am looking for something templates that lets you re-use the code for different situations.
I have found a couple of tutorials but they all use PHP:
Bokehman - This website says it uses Javascript, but it actually uses PHP
Code Canyon - This script is templated to easily swap out elements, but again uses PHP.
I know that Javascript really doesn't support writing files so you would have to use a PHP solution to save the image.
However, I am just looking for something to create the image. At this stage, I'm not bothered about the saving.
This is how I did it in the end.
1) Create a separate CSS classes for each asset.
Concatenate classes for assets that are made up of multiple variables.
Create a .input parent class to display image assets for the selection form.
Create a .preview child class to display image assets on the finished avatar
e.g.
.skin-brown .preview .preview-body {
background-image(<<image-asset>>);
}
.input .input-skin-brown {
background-image(<<image-asset>>);
}
.input .input-hair-style-1 {
background-image(<<image-asset>>);
}
.hair-style-1.hair-colour-black .preview .preview-hair {
background-image(<<image-asset>>);
}
2) Create HTML. Assign default asset options to the wrapper element.
e.g.
<div id="wrapper" class="hair-style-1 hair-colour-black skin-brown">
<div class="inputs">
Put your input FORM here. Use a HTML form element.
</div>
<div class="preview">
The finished avatar goes here.
<div class="preview-hair"></div>
<div class="preview-eyes"></div>
<div class="preview-body"></div>
</div>
</div>
3) Use Jquery to manipulate the classes on the wrapper when the options in the input form have been clicked.
e.g if user clicks on hair-style-2, the hair-style-1 class in the wrapper will be changed to hair-style-2
I have a separate question about this:
jQuery: Swap Classes based on Class position
That's essentially all there is to it. Once you have the css classes written and the Jquery code to switch the classes working, it is actually very straightforward.
Because you a storing all the inputs as a form, you can send the values to another process when the user clicks submit.
Tips:
1) Use SASS/SCSS to write the css.
You can create an array and loop through it in sass which makes it easy to maintain the css. I have a question about this here:
Sass: Using two #each lists in SCSS
CSS - SASS: Using #each based mixins to generate multiple backgrounds
2) Avoid using a CSS sprite.
Although sprites help greatly with load times, I think you will go crazy trying to maintain it (depending on the assets that are involved). There are tools to maintain it for you, but because this is an edge case, I don't think the tools work that well.
3) Load Speeds are an issue
When the user clicks on an avatar element, there is a short delay while the CSS loads. This is a problem, as the user thinks their click hasn't registered.
To get around this, create a hidden div, which uses display:none. Then use the CSS3 multiple background property to attach every asset to this DIV (as a background).
This way, all your assets will load at the start, so there won't be a delay when the user clicks. Again, use SASS loops and arrays for this, as the array will automatically add all your assets to the hidden DIV.
4) Think very carefully about class and asset names.
I originally went for friendly names (e.g. haircolourblack, hairstylebob) as I thought it would be easier to make sense of the code. However, in hindsight, I wish I had gone for numbered names (haircolour1, hairstyle1) as things can get tricky if your assets change (Plus using numbers make it easy to maintain code against multiple avatars). Again, use SASS arrays to cut down on the maintenance of this.
5) Use Class prefixes
(e.g. .preview .preview-eye instead of .preview .eye or .preview .preview-hair-style instead of .preview .hair ). The reason for this is that a lot of the names are very generic and will probably be used in multiple places on the page (e.g. for both .preview and .input sections). If you use prefixes, it is easier to target specific classes. Plus you can use [class*="preview-"] or [class*="input-"] to target all members of a prefix, without having to litter your code with lots of shared classes (e.g. [class*="-hair-"] will get all hair elements without needing a separate hair class applied to each hair element.
6) Consider SVG
If you use SVG for your image assets, you can keep the files small and they will scale up to any size. Be sure to note SVG browser compatibility (http://caniuse.com/svg)
7) Consider CSS background size
You can also use background-size: contain to scale image assets, which can make it easy to reuse the same image for both .preview and .input instances. However, it also has compatibility issues.
It does seem like a daunting project, mainly because there aren't any resources on how to build it. But if you break it down, it's actually quite easy. It's mainly the code maintenance that is an issue, so be sure to plan!

Webkit columns find range of visible text

I have a piece of HTML which I am displaying inside a UIWebView using Webkit stylesheet attributes. I use Webkit to display the HTML in columns in order to simulate a book.
Only one column is visible at a time (one column represents one page). Now, I am trying to find the range of the visible HTML so that I can insert a span element right before the first visible word.
I managed to get the HTML element which contains the first visible word by using the JavaScript function, document.elementAtPoint(I might have the function name wrong), and changed its CSS class. but that just isn't accurate enough for me. I need it to be accurate up to the first visible word.
The idea is the create a column break at the first visible word when the fontsize is increased or decreased. I can using JavaScript to figure out in which column the element is, and programmatically scroll the user to that column, but first I need to get the element in there.
Can anyone help me?
The CSSOM View Module specification adds caretPositionFromPoint(x, y) to the Document interface, which returns a caret position for the specified x and y co-ordinates. WebKit supports caretRangeFromPoint, a close analogue from an earlier specification, which returns a Range.
It is possible that the word has been hyphenated and thus spans two columns, so rather than wrapping the first word in a span you may wish to consider the more naive approach of inserting the span directly at the cursor point. Here's an example:
var caretPos = document.caretRangeFromPoint(x, y);
if (caretPos)
caretPos.insertNode(document.createElement('span'));
Demo (WebKit only—click to insert spans): http://jsfiddle.net/Jordan/Aw9aV/
One final consideration: it is possible that WebKit will eventually stop supporting caretRangeFromPoint in lieu of caretPositionFromPoint; if so, you will need to adapt your code. Also note that the latter returns a CaretPosition which may not implement the insertNode method. The spec is still at WD, so be mindful that it is still in flux.
Ok, nog entirely sure what you are currently doing, but at the very least I should be able to give some useful tips, as I have some experience building page browsing systems in javascript.
First of all, in CSS3 you can define columns https://developer.mozilla.org/en/CSS3_Columns , which will automatically split up the content into different columns within a single element (where a single column has the full width of the uiwebview) and next add browsing controls which move the entire element containing the element (using css3 3d translations for smooth hardware accelerated motion and you know the width of the columns so you don't need to worry about what the first word on the page is). In which case you don't need to worry about splitting up the column breaks yourself. (Though, as I said, I am not sure to what extend you are already doing this).
Alternatively you may decide to wrap all your content in small inline-blocks (as older column implementations did) or even up to the point of single inline elements, each containing a single word. (Though this doesn't seem necessary anymore)
Lastly, work is being done on http://www.w3.org/TR/css3-regions/ which will make this even easier in the future, but for now it's only available in chrome and ie10
On the other hand, you might already be doing this or I might be missing the point, in which case I would need to see some code before I can give you a more specific answer. (I can think of various javascript tricks to work with letters within a text, but none seem necessary in your case)

Categories