419

Like most web developers, I occasionally like to look at the source of websites to see how their markup is built. Tools like Firebug and Chrome Developer Tools make it easy to inspect the code, but if I want to copy a specific section and play around with it locally, it would be a pain to copy all the individual elements and their associated CSS. And probably just as much work to save the entire source and cut out the unrelated code.

It would be great if I could right-click a Element in Firebug and have a "Save HTML+CSS+JS for this Element" option. Does such a tool exist? Is it possible to extend Firebug or Chrome Developer Tools to add this feature?

kenwarner
  • 27,129
  • 27
  • 126
  • 170
  • 5
    Just wanted to add (not a tool as you describe, so not making an answer), if you use chrome you can select an element and look at the "Computed Style" on the right in the css section. You would be able to copy-paste the entire list into a style. It's an extra step from a tool you want, but gives you the css you are looking for. – riv_rec Oct 18 '11 at 04:04
  • 2
    Not a complete answer to your question, but F2 in Chrome dev tools on the "Elements" tab will open up the chosen DOM element and subtree for inline editing (and copying if you want). – 10gistic Sep 27 '13 at 23:45
  • 1
    One very interesting extension of chrome is the "Save All Resources". Install it and then navigate to "Resources Saver" of Chrome Dev Tool tab and download it! – dimeros Nov 02 '19 at 22:14

16 Answers16

599

SnappySnippet

I finally found some time to create this tool. You can install SnappySnippet from Github. It allows easy HTML+CSS extraction from the specified (last inspected) DOM node. Additionally, you can send your code straight to CodePen or JSFiddle. Enjoy!

SnappySnippet Chrome extension

Other features

  • cleans up HTML (removing unnecessary attributes, fixing indentation)
  • optimizes CSS to make it readable
  • fully configurable (all filters can be turned off)
  • works with ::before and ::after pseudo-elements
  • nice UI thanks to Bootstrap & Flat-UI projects

Code

SnappySnippet is open source, and you can find the code on GitHub.

Implementation

Since I've learned quite a lot while making this, I've decided to share some of the problems I've experienced and my solutions to them, maybe someone will find it interesting.

First attempt - getMatchedCSSRules()

At first I've tried retrieving the original CSS rules (coming from CSS files on the website). Quite amazingly, this is very simple thanks to window.getMatchedCSSRules(), however, it didn't work out well. The problem was that we were taking only a part of the HTML and CSS selectors that were matching in the context of the whole document, which were not matching anymore in the context of an HTML snippet. Since parsing and modifying selectors didn't seem like a good idea, I gave up on this attempt.

Second attempt - getComputedStyle()

Then, I've started from something that @CollectiveCognition suggested - getComputedStyle(). However, I really wanted to separate CSS form HTML instead of inlining all styles.

Problem 1 - separating CSS from HTML

The solution here wasn't very beautiful but quite straightforward. I've assigned IDs to all nodes in the selected subtree and used that ID to create appropriate CSS rules.

Problem 2 - removing properties with default values

Assigning IDs to the nodes worked out nicely, however I found out that each of my CSS rules has ~300 properties making the whole CSS unreadable.
Turns out that getComputedStyle() returns all possible CSS properties and values calculated for the given element. Some of them where empty, some had browser default values. To remove default values I had to get them from the browser first (and each tag has different default values). The solution was to compare the styles of the element coming from the website with the same element inserted into an empty <iframe>. The logic here was that there are no style sheets in an empty <iframe>, so each element I've appended there had only default browser styles. This way I was able to get rid of most of the properties that were insignificant.

Problem 3 - keeping only shorthand properties

Next thing I have spotted was that properties having shorthand equivalent were unnecessarily printed out (e.g. there was border: solid black 1px and then border-color: black;, border-width: 1px itd.).
To solve this I've simply created a list of properties that have shorthand equivalents and filtered them out from the results.

Problem 4 - removing prefixed properties

The number of properties in each rule was significantly lower after the previous operation, but I've found that I sill had a lot of -webkit- prefixed properties that I've never hear of (-webkit-app-region? -webkit-text-emphasis-position?).
I was wondering if I should keep any of these properties because some of them seemed useful (-webkit-transform-origin, -webkit-perspective-origin etc.). I haven't figured out how to verify this, though, and since I knew that most of the time these properties are just garbage, I decided to remove them all.

Problem 5 - combining same CSS rules

The next problem I have spotted was that the same CSS rules are repeated over and over (e.g. for each <li> with the exact same styles there was the same rule in the CSS output created).
This was just a matter of comparing rules with each other and combining these that had exactly the same set of properties and values. As a result, instead of #LI_1{...}, #LI_2{...} I got #LI_1, #LI_2 {...}.

Problem 6 - cleaning up and fixing indentation of HTML

Since I was happy with the result, I moved to HTML. It looked like a mess, mostly because the outerHTML property keeps it formatted exactly as it was returned from the server.
The only thing HTML code taken from outerHTML needed was a simple code reformatting. Since it's something available in every IDE, I was sure that there is a JavaScript library that does exactly that. And it turns out that I was right (jquery-clean). What's more, I've got unnecessary attributes removal extra (style, data-ng-repeat etc.).

Problem 7 - filters breaking CSS

Since there is a chance that in some circumstances filters mentioned above may break CSS in the snippet, I've made all of them optional. You can disable them from the Settings menu.

Konrad Dzwinel
  • 33,802
  • 12
  • 91
  • 100
  • @KonradDzwinel, I'm looking for a way to do this programmatically within a page (For printing a specific DOM subtree, just copy it to a new window and [`print()`](https://developer.mozilla.org/en-US/docs/Web/API/Window.print)). How hard would it be (for you or for someone to looking to fork your repo) to make this in JS alone as a callable function? – Hashbrown Oct 01 '13 at 06:26
  • @Hashbrown Mail me and we can talk details - I think it will be pretty simple. – Konrad Dzwinel Oct 01 '13 at 08:11
  • @KonradDzwinel thank you so much for the effort, but what if i want to get the node element with the php function 'file_get_contents($url)', is there any solution, here is my post : http://stackoverflow.com/questions/21419857/tool-will-help-me-to-get-all-the-css-and-javascript-related-with-an-html-tag – Yassine edouiri Jan 29 '14 at 17:37
  • Great work! but is it possible to include the js code that acts on the element? – t31321 Dec 31 '14 at 13:41
  • And you say it was inspired by this question? You sure went the extra mile. That said, it doesn't actually work for me, and I'll say it for the sake of people with similar requirements. What I need is to keep the adaptive resizing stuff intact, and as I understand it, a solution based on getComputedStyle can't do that. – mc0e Apr 26 '15 at 20:37
  • For those who are not happy with the fixed sizes (getComputedStyle), you maybe should have a look at this : http://www.betterprogramming.com/htmlclipper.html – fro_oo Jul 04 '15 at 13:44
  • man it delete all the classes ... I need to reuse my work ... all ID is not accepted at all – J.Tural Dec 25 '15 at 04:58
  • A +1 on the amazing plugin, for sure. However, it doesn't work with CSS sprites, which is a bit of a bummer. – David Keaveny Feb 01 '16 at 05:25
  • @DavidKeaveny can you please report that here: https://github.com/kdzwinel/SnappySnippet/issues ? Thanks! – Konrad Dzwinel Feb 01 '16 at 09:19
  • 1
    @KonradDzwinel someone has already beaten me to it: https://github.com/kdzwinel/SnappySnippet/issues/37. – David Keaveny Feb 01 '16 at 21:49
  • If it could take media queries was very helpful. Some DOM Elements have different styles in different sizes. – Iman Sedighi Nov 22 '16 at 08:01
  • Is there any way to copy the associated Javascript or Jquery along with css ? – John Jan 16 '17 at 13:08
  • Could it copy the relevant javascript code bind to the selected element? – Ryan Chou Dec 18 '18 at 11:32
  • @KonradDzwinel; have you got suggestion on how to copy javascript too? – Revious Jul 23 '19 at 15:24
  • THAT'S engagement :) Wow, seeing a problem and writing software for it! My biggest respect to you! – Sliq Nov 26 '19 at 14:58
56

I originally asked this question I was looking for a Chrome (or FireFox) solution, but I stumbled across this feature in Internet Explorer developer tools. Pretty much what I'm looking for (except for the javascript)

Element Source with Style

Result:

Element Source with Style result

kenwarner
  • 27,129
  • 27
  • 126
  • 170
  • 7
    IE11 also works. But the option is accessible from right click directly on element. – Rodolfo Jorge Nemer Nogueira Aug 20 '14 at 13:20
  • 23
    Wow, finally an example where IE devtools are superior! – dmnd Sep 03 '14 at 01:29
  • 9
    Best solution I have tried compare to all others listed in this page. The generated CSS+HTML is super clean while keeping original css names, meaning that the html is same as the original. – xoofx Nov 11 '14 at 01:29
  • 2
    Holy crap that is awesome. Can confirm @xoofx 's findings that the HTML markup remains the same but wanted to comment further that it also outputs skeleton parent wrapping elements needed to truly match the style. – Daniel Sokolowski Nov 08 '15 at 01:52
  • Used this. Couldn't get snappy snippet to work correctly (complex html & css). I can't believe this actually worked. And just so people know, I didn't see this feature in edge just explorer. – Watson Nov 07 '16 at 18:50
  • @Watson right click the element and a button will say "copy element with styles" https://i.imgur.com/p5MeO3N.png –  Dec 16 '17 at 00:07
  • It gets no CSS3 media queries on IE 11, other than that, it's fine – cawecoy Oct 17 '20 at 17:53
53

Webkit browsers (not sure about FireBug) allow you to copy the HTML of an element easily, so that's one part of the process out of the way.

Running this (in the javascript console) prior to copying the HTML for an element will move all the computed styles for the parent element given, as well as all child elements, into the inline style attribute which will then be available as part of the HTML.

var el = document.querySelector("#someid");
var els = el.getElementsByTagName("*");

for(var i = -1, l = els.length; ++i < l;){

    els[i].setAttribute("style", window.getComputedStyle(els[i]).cssText);

}

It's a total hack and you'll have alot of "junk" css attributes to wade through, but should at least get your started.

  • 3
    Great answer, but...unrelated to the actual answer, whats with the for...loop syntax? It reads as obfuscated to me. – Steve Campbell Sep 10 '12 at 13:05
  • 1
    This is great, just misses the root element. Add this too: el.setAttribute("style", window.getComputedStyle(el).cssText); – Karman Kertesz Nov 29 '12 at 11:04
  • in chrome console, .querySelector returned null for me. So change it to the following and it worked: var el = document.getElementById("#someid"); el.setAttribute("style", window.getComputedStyle(el).cssText); var els = el.getElementsByTagName("*"); for(var i = -1, l = els.length; ++i < l;){ els[i].setAttribute("style", window.getComputedStyle(els[i]).cssText); } – Viktor Tango Apr 24 '14 at 20:03
31

I've created this tool years ago for the same purpose:
http://www.betterprogramming.com/htmlclipper.html

You're welcome to use and improve upon it.

Florentin
  • 621
  • 7
  • 8
  • This is exactly what I need right now. Many thanks... thinking of this solution available 4 years ago... – fro_oo Jul 04 '15 at 13:43
26

This can be done by Firebug Plugin called scrapbook

You can check Javascript option in setting

enter image description here

Edit:

This can also help

Firequark is an extension to Firebug to aid the process of HTML Screen Scraping. Firequark automatically extracts css selector for a single or multiple html node(s) from a web page using Firebug (a web development plugin for Firefox). The css selector generated can be given as an input to html screen scrapers like Scrapi to extract information. Firequark is built to unleash the power of css selector for use of html screen scraping.

nathanchere
  • 7,540
  • 14
  • 60
  • 84
Jitendra Vyas
  • 134,556
  • 218
  • 544
  • 822
  • 1
    Scrapbook looks great - unfortunately both the latest version (1.4.5) and a previous one recommended in the reviews (1.4.3) wouldn't work for me on OSX/FF3.6.1. Anyone have this working? – peteorpeter May 16 '11 at 13:17
  • i wish i could more precisely select a node to save, but this worked pretty well – kenwarner May 22 '11 at 02:39
  • 1
    This is kinda helpful, but didn't solve my need for moving a page element with required css to another page. Scrapbook copies all of the pages css, whether it's needed or not for the selected part of the page, and it doesn't do any rewriting of the css that would help avoid the styles colliding with the css of another page. – mc0e Apr 26 '15 at 20:42
14

divclip is an updated version of Florentin Sardan's htmlclipper

with modern enhancements: ES5, HTML5, scoped CSS...

you can programmatically extract a stylized div with:

var html = require("divclip").bySel(".article-body");
console.log(html);

Enjoy.

Community
  • 1
  • 1
ato3787045
  • 165
  • 2
  • 8
  • 1
    great one! works like a charm! i did some modification so that it can just run in chrome. just remove the 'export' and 'require' dependency , and copy them to chrome snippet. then can in the console, type `copy(divclip.bySel('.topbar'))` which will copy the processed output to the clipboard! ;) – ken Sep 23 '15 at 15:10
  • have an error: shellprod.msocdn.com/16.00.1692.002/en-US/JSC/O365ShellG2Plus.js:21 Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://portal.office.com') does not match the recipient window's origin ('null'). – Slava Mar 27 '17 at 22:38
12

There is no plugins needed. It can be done very simply with Internet Explorer 11 native Developer Tools with just one click, very clean. Just right on an element and inspect that element, and right click on some block and choose "Copy element with styles". You can see it in the below image.

It provides the css code very clean, like

.menu { 
    margin: 0;
}
.menu li {
    list-style: none;
}
GarryOne
  • 998
  • 9
  • 16
  • Wow, this worked perfectly in Microsoft Edge. Tried htmlclipper and snappysnippet but had issues retaining the responsiveness of elements I'm trying to copy. – Matt Aug 04 '17 at 02:45
  • this is amazing, works perfectly well. – snit80 Mar 03 '20 at 02:03
6

Lately I created a chrome extension "eXtract Snippet" for copying the inspected element, html and only the relevant css and media queries from a page. Note that this would give you the actual relevant CSS

https://chrome.google.com/webstore/detail/extract-snippet/bfcjfegkgdoomgmofhcidoiampnpbdao?hl=en

melwyn pawar
  • 1,666
  • 2
  • 15
  • 20
3

http://clipboardjs.com does this and quite well. Although your expectation of the copied version being exactly as in the original so you can play and learn with it, may not be realistic.

Samuel Liew
  • 68,352
  • 105
  • 140
  • 225
Moin Zaman
  • 24,413
  • 5
  • 65
  • 73
3

A tool with a single solution for this I'm unaware of, but you can use Firebug and Web Developer extension at the same time.

Use Firebug to copy the html section you need (Inspect Element) and Web Developer to see which css is associated with an element (Calling Web Developer "View Style Information" - it works like Firebug's "Inspect Element", but instead of showing the html markup it shows the associated CSS with that markup).

It's not exactly what you want (one click for everything), but it's pretty close, and at least intuitive.

'View Style Information' result from Web Developer Extension

GmonC
  • 10,803
  • 1
  • 27
  • 37
  • This is what I do, but it involves manually copying the CSS for each element. What I think the OP wants ideally is something that can copy the CSS styles affecting an element and all nested elements -- copying it in one go like you do for the HTML. – Muhd Jan 19 '13 at 01:38
3

I also need this feature on Firebug! Until then, another approach is to use this online service to remove classes and convert the css to inline styles.

VMAtm
  • 26,645
  • 17
  • 75
  • 107
Acyra
  • 15,026
  • 15
  • 41
  • 51
2

Just copy the part you want from the webpage and paste it in the wysiwyg editor. Check the html source by clicking on the "source" button on the editor toolbar.

I've found this most easiest way when I was working on a Drupal site. I use wysiwyg CKeditor.

Kevin Siji
  • 261
  • 2
  • 8
2
jQuery.fn.extend({
getStyles: function() {
    var rulesUsed = [];
    var sheets = document.styleSheets;
    for (var c = 0; c < sheets.length; c++) {
        var rules = sheets[c].rules || sheets[c].cssRules;
        for (var r = 0; r < rules.length; r++) {
            var selectorText = rules[r].selectorText.toLowerCase().replace(":hover","");
            if (this.is(selectorText) || this.find(selectorText).length > 0) {
                rulesUsed.push(rules[r]);
            }
        }
    }
    var style = rulesUsed.map(function(cssRule) {
        return cssRule.selectorText.toLowerCase() + ' { ' + cssRule.style.cssText.toLowerCase() + ' }';
    }).join("\n");
    return style;
}
});

usage:$("#login_wrapper").getStyles()

geekbytes0xff
  • 193
  • 1
  • 7
  • For my need, this looks quite promising, as it avoids the limitations of getComputedStyle. I'm just too much of a javascript noob to be sure how to use it to get the actual text of the css. – mc0e Apr 26 '15 at 20:51
  • I've changed the usage to use `jQuery` instead of `$`, which gets me a little way, but now I get `SecurityError: The operation is insecure.` Any pointers? – mc0e Apr 26 '15 at 21:08
0

I gone through all the tools mentioned as answer here. But they give repeated, dirty HTML CSS with beautiful face you were staring up on. They don't give you JS.

What I do:

  1. First I filter ads which are not require on the page
  2. Then , save complete webpage along with linking resources.
  3. Remove unnecessary HTML, CSS and JS
  4. keep unlinking resources one-by-one carefully.
Amit Kumar Gupta
  • 6,271
  • 11
  • 54
  • 77
0

There is a firefox plugin that saves the whole page's HTML, CSS, etc.. but I have not seen one that does a partial save.

I remember IE 5.5 had what you were looking for though ;)

Sudarshan
  • 16,642
  • 7
  • 46
  • 59
Chris Abrams
  • 32,712
  • 19
  • 49
  • 56
0

I've adapted the top voted answer as a dragabble bookmarklet.

Just visit this page and drag the "Run jQuery Code" button to your bookmark bar.

Community
  • 1
  • 1
ripper234
  • 202,011
  • 255
  • 600
  • 878